Activity的起步流程分析

poclist發表於2016-09-17

Activity的起步流程分析

www.MyException.Cn  網友分享於:2015-10-15  瀏覽:0次
Activity的啟動流程分析

為了在手機畫面上顯示Activity的window,android內部會做一下內容:

  1) 建立一個Window在Window裡構建View Hierachy。

  2) 與WindowManager建立聯絡。

  3) 為了與SystemServer通訊,開啟Binder裝置。

  4) 把Window註冊上去,確定View Hierachy大小,位置。

  5) 確定大小,位置後在Surface中開始Draw。

  6) 把Surface輸出在LCD中。

  就這樣我們就能從手機螢幕中看到了。

 

Activity的啟動簡單來說就兩種:

  1. 點選應用程式圖示啟動Activity( luncher啟動 )。
  2. 從一個Activity跳轉到另一個Activity ( 也就是說從一個Activity中執行startActivity() )。

 

首先我們看一下Manifast.xml檔案(為了體現兩種啟動方式而自定義的Manifast)

<?xml version="1.0" encoding="utf-8"?>    
<manifest xmlns:android="http://schemas.android.com/apk/res/android"    
    package="android.com.activitytest"    
    android:versionCode="1"    
    android:versionName="1.0">    
    <application android:icon="@drawable/icon" android:label="@string/app_name">   

    <!-- MainActivity是點選應用程式圖示來啟動Activity--> 
      <activity android:name=".MainActivity"    
                  android:label="@string/app_name">    
            <intent-filter>    
                <action android:name="android.intent.action.MAIN" />    
                <category android:name="android.intent.category.LAUNCHER" />    
            </intent-filter>    
        </activity>    
    <!-- SubActivity是MainActivity呼叫startActivity函式來啟動Activity-->
        <activity android:name=".SubActivity" android:label="@string/sub_activity">        
        </activity>    

    </application>    
</manifest>  

 

1. MainActivity的啟動

首先我們先分析MainActivity的啟動

分析之前我們先看一下Manifast中的 <category android:name="android.intent.category.LAUNCHER" /> ,表示要用LAUNCHER啟動。

  • Launcher:Launcher本身也是一個應用程式,其它的應用程式安裝後,就會Launcher的介面上出現一個相應的應用程式圖示。

當我們點選相應的應用程式圖示時,Launcher就會啟動對應的應用程。

 

下面是Launcher的原始碼

public final class Launcher extends Activity  
        implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks, AllAppsView.Watcher {  
  
    ......  
  
    /** 
    * Launches the intent referred by the clicked shortcut. 
    * 
    * @param v The view representing the clicked shortcut. 
    */  
    public void onClick(View v) {  
        Object tag = v.getTag();  
        if (tag instanceof ShortcutInfo) {  
            // Open shortcut  
            final Intent intent = ((ShortcutInfo) tag).intent;  
            int[] pos = new int[2];  
            v.getLocationOnScreen(pos);  
            intent.setSourceBounds(new Rect(pos[0], pos[1],  
                pos[0] + v.getWidth(), pos[1] + v.getHeight()));  
            startActivitySafely(intent, tag);  
        } else if (tag instanceof FolderInfo) {  
            ......  
        } else if (v == mHandleView) {  
            ......  
        }  
    }  
  
    void startActivitySafely(Intent intent, Object tag) {  
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
        try {  
            startActivity(intent);  
        } catch (ActivityNotFoundException e) {  
            ......  
        } catch (SecurityException e) {  
            ......  
        }  
    }  
  
    ......  
  
}

從程式碼中可知,當我們點選某個應用程式圖示時會觸發Launcher的public void onClick(View v)點選事件。
然後呼叫ShortcutInfo中的startActivitySafely(intent, tag);- > startActivity(intent);。

  • Intent.FLAG_ACTIVITY_NEW_TASK:表示要在一個新的Task中啟動這個Activity。

startActivity函式是啟動的Activity的startActivity函式。

 

frameworks/base/core/java/android/app/Activity.java

public class Activity extends ContextThemeWrapper  
        implements LayoutInflater.Factory,  
        Window.Callback, KeyEvent.Callback,  
        OnCreateContextMenuListener, ComponentCallbacks {  
  
    ......  
  
    @Override  
    public void startActivity(Intent intent) {  
        startActivityForResult(intent, -1);  
    }  
  
    ......  
  
} 

還會呼叫startActivityForResult來進一步處理,第二個引數傳入-1表示不需要這個Actvity結束後的返回結果。

public class Activity extends ContextThemeWrapper  
        implements LayoutInflater.Factory,  
        Window.Callback, KeyEvent.Callback,  
        OnCreateContextMenuListener, ComponentCallbacks {  
  
    ......  
  
    public void startActivityForResult(Intent intent, int requestCode) {  
        if (mParent == null) {  
            Instrumentation.ActivityResult ar =  
                mInstrumentation.execStartActivity(  
                this, mMainThread.getApplicationThread(), mToken, this,  
                intent, requestCode);  
            ......  
        } else {  
            ......  
        }  
  
  
    ......  
  
}  

frameworks/base/core/java/android/app/Instrumentation.java

public class Instrumentation {  
  
    ......  
  
    public ActivityResult execStartActivity(  
    Context who, IBinder contextThread, IBinder token, Activity target,  
    Intent intent, int requestCode) {  
        IApplicationThread whoThread = (IApplicationThread) contextThread;  
        if (mActivityMonitors != null) {  
            ......  
        }  
        try {  
            int result = ActivityManagerNative.getDefault()  
                .startActivity(whoThread, intent,  
                intent.resolveTypeIfNeeded(who.getContentResolver()),  
                null, 0, token, target != null ? target.mEmbeddedID : null,  
                requestCode, false, false);  
            ......  
        } catch (RemoteException e) {  
        }  
        return null;  
    }  
  
    ......  
  
} 

重要角色出來了ActivityManagerNative.getDefault()返回ActivityManagerService。
ActivityManagerService是在另外一個程式中所以需要呼叫它的代理服務。即ActivityManagerProxy。

frameworks/base/core/java/android/app/ActivityManagerNative.java(內部類)

class ActivityManagerProxy implements IActivityManager  
{  
  
    ......  
  
    public int startActivity(IApplicationThread caller, Intent intent,  
            String resolvedType, Uri[] grantedUriPermissions, int grantedMode,  
            IBinder resultTo, String resultWho,  
            int requestCode, boolean onlyIfNeeded,  
            boolean debug) throws RemoteException {  
        Parcel data = Parcel.obtain();  
        Parcel reply = Parcel.obtain();  
        data.writeInterfaceToken(IActivityManager.descriptor);  
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);  
        intent.writeToParcel(data, 0);  
        data.writeString(resolvedType);  
        data.writeTypedArray(grantedUriPermissions, 0);  
        data.writeInt(grantedMode);  
        data.writeStrongBinder(resultTo);  
        data.writeString(resultWho);  
        data.writeInt(requestCode);  
        data.writeInt(onlyIfNeeded ? 1 : 0);  
        data.writeInt(debug ? 1 : 0);  
        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);  
        reply.readException();  
        int result = reply.readInt();  
        reply.recycle();  
        data.recycle();  
        return result;  
    }  
  
    ......  
  
}

最終還會呼叫ActivityManagerService(frameworks/base/services/java/com/android/server/am/ActivityManagerService.java)的startActivity函式

而在此函式中沒有其他動作,僅僅做了一個轉發,呼叫了ActivityStack.startActivityMayWait函式

frameworks/base/services/java/com/android/server/am/ActivityStack.java

public class ActivityStack {  
  
    ......  
  
    final int startActivityMayWait(IApplicationThread caller,  
            Intent intent, String resolvedType, Uri[] grantedUriPermissions,  
            int grantedMode, IBinder resultTo,  
            String resultWho, int requestCode, boolean onlyIfNeeded,  
            boolean debug, WaitResult outResult, Configuration config) {  
  
        ......  
  
        boolean componentSpecified = intent.getComponent() != null;  
  
        

        intent = new Intent(intent);  
  
        // 解析AndroidManifest.xml,得知activity的報名及activity的類名。
        ActivityInfo aInfo;  
        try {  
            ResolveInfo rInfo =  
                AppGlobals.getPackageManager().resolveIntent(  
                intent, resolvedType,  
                PackageManager.MATCH_DEFAULT_ONLY  
                | ActivityManagerService.STOCK_PM_FLAGS);  
            aInfo = rInfo != null ? rInfo.activityInfo : null;  
        } catch (RemoteException e) {  
            ......  
        }  
  
        if (aInfo != null) {  
            // 指定具體的元件類,通知應用啟動對應的元件。
            intent.setComponent(new ComponentName(  
                aInfo.applicationInfo.packageName, aInfo.name));  
            ......  
        }  
  
        synchronized (mService) {  
            int callingPid;  
            int callingUid;  
            if (caller == null) {  
                ......  
            } else {  
                callingPid = callingUid = -1;  
            }  
  
            mConfigWillChange = config != null  
                && mService.mConfiguration.diff(config) != 0;  
  
            ......  
  
            if (mMainStack && aInfo != null &&  
                (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {  
                    
                      ......  
  
            }  
  
            int res = startActivityLocked(caller, intent, resolvedType,  
                grantedUriPermissions, grantedMode, aInfo,  
                resultTo, resultWho, requestCode, callingPid, callingUid,  
                onlyIfNeeded, componentSpecified);  
  
            if (mConfigWillChange && mMainStack) {  
                ......  
            }  
  
            ......  
  
            if (outResult != null) {  
                ......  
            }  
  
            return res;  
        }  
  
    }  
  
    ......  
  
}  

最後呼叫startActivityLocked
frameworks/base/services/java/com/android/server/am/ActivityStack.java

public class ActivityStack {  
  
    ......  
  
    final int startActivityLocked(IApplicationThread caller,  
            Intent intent, String resolvedType,  
            Uri[] grantedUriPermissions,  
            int grantedMode, ActivityInfo aInfo, IBinder resultTo,  
                String resultWho, int requestCode,  
            int callingPid, int callingUid, boolean onlyIfNeeded,  
            boolean componentSpecified) {  
            int err = START_SUCCESS;  
  
        ProcessRecord callerApp = null;  
        if (caller != null) {  
            callerApp = mService.getRecordForAppLocked(caller);  
            if (callerApp != null) {  
                callingPid = callerApp.pid;  
                callingUid = callerApp.info.uid;  
            } else {  
                ......  
            }  
        }  
  
        ......  
  
        ActivityRecord sourceRecord = null;  
        ActivityRecord resultRecord = null;  
        if (resultTo != null) {  
            int index = indexOfTokenLocked(resultTo);  
              
            ......  
                  
            if (index >= 0) {  
                sourceRecord = (ActivityRecord)mHistory.get(index);  
                if (requestCode >= 0 && !sourceRecord.finishing) {  
                    ......  
                }  
            }  
        }  
  
        int launchFlags = intent.getFlags();  
  
        if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0  
            && sourceRecord != null) {  
            ......  
        }  
  
        ......  
  
        ActivityRecord r = new ActivityRecord(mService, this, callerApp, callingUid,  
            intent, resolvedType, aInfo, mService.mConfiguration,  
            resultRecord, resultWho, requestCode, componentSpecified);  
  
        ......  
  
        return startActivityUncheckedLocked(r, sourceRecord,  
            grantedUriPermissions, grantedMode, onlyIfNeeded, true);  
    }  
  
  
    ......  
  
}

從caller(ApplicationThread)中獲取程式(launcher程式)資訊儲存在ProcessRecord callerApp=mService.getRecordForAppLocked(caller);

建立即將要啟動的Activity的相關資訊ActivityRecord r = new ActivityRecord函式。

而在startActivityUncheckedLocked函式中把Task儲存在r.task域中,同時,新增到mService中去,這裡的mService就是ActivityManagerService了。呼叫startActivityLocked(r, newTask, doResume)

 

frameworks/base/services/java/com/android/server/am/ActivityStack.java

public class ActivityStack {  
  
    ......  
  
    private final void startActivityLocked(ActivityRecord r, boolean newTask,  
            boolean doResume) {  
        final int NH = mHistory.size();  
  
        int addPos = -1;  
  
        if (!newTask) {  
            ......  
        }  
  
        // Place a new activity at top of stack, so it is next to interact  
        // with the user.  
        if (addPos < 0) {  
            addPos = NH;  
        }  
  
        // If we are not placing the new activity frontmost, we do not want  
        // to deliver the onUserLeaving callback to the actual frontmost  
        // activity  
        if (addPos < NH) {  
            ......  
        }  
  
        // Slot the activity into the history stack and proceed  
        mHistory.add(addPos, r);  
        r.inHistory = true;  
        r.frontOfTask = newTask;  
        r.task.numActivities++;

     //NH表示當前系統中歷史任務的個數  
        if (NH > 0) {  
            // We want to show the starting preview window if we are  
            // switching to a new task, or the next activity's process is  
            // not currently running.  
            ......  
        } else {  
            // If this is the first activity, don't do any fancy animations,  
            // because there is nothing for it to animate on top of.  
            ......  
        }  
          
        ......  
  
        if (doResume) {  
            resumeTopActivityLocked(null);  
        }  
    }  
  
    ......  
  
}

resumeTopActivityLocked(null);  函式獲得堆疊頂端的Activity,即MainActivity。

MainActivity建立了ActivityRecord後,它的app域一直保持為null。有了這些資訊後,上面這段程式碼就容易理解了,它最終呼叫startSpecificActivityLocked進行下一步操作。

rameworks/base/services/java/com/android/server/am/ActivityStack.java

public class ActivityStack {

    ......

    private final void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // 由於是第一次啟動應用程式的Activity,所以下面語句
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
            r.info.applicationInfo.uid);

        ......

        if (app != null && app.thread != null) {
            try {
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
                ......
            }
        }

        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
            "activity", r.intent.getComponent(), false);
    }


    ......

}

mService.getProcessRecordLocked此函式是在AMS中,路徑如下

frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

在此函式中建立一個ProcessRecord,呼叫startProcessLocked。

frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

startProcessLocked函式中:

 int pid = Process.start("android.app.ActivityThread",  
                mSimpleProcessManagement ? app.processName : null, uid, uid,  
                gids, debugFlags, null);  

在這我們可以看到他會啟動一個Process,而這個Process由Zygote建立的。在前幾節中我們講過有關Zygote,在那裡我們提過Zygote的客戶端也可以是AMS。從這裡我們可以看出這一點。

接下來通過ActivityThread會呼叫Activity的onCread()。

 

2. SubActivity的啟動

  其實利用MainActivity中的元件(如:button.onclick)去startActivity是與Launcher中啟動時一樣的,從上面分析的內容中可以看出Luancher最終也會呼叫startActivity。

  僅僅是呼叫subActivity時不會建立一個Process,僅僅利用當場執行緒去建立而已。然後退回到Main函式時時從ActivityStack中Pause的Activity重新顯現出來。

可以參考下面的圖:

 

相關文章