Task&Activity&ActivityRecord...

来源:互联网 发布:吉林破获特大网络诈骗 编辑:程序博客网 时间:2024/06/06 08:25

1、Activity
2、Stack
3、Task :一个Task是一系列Activity的集合,这个集合是以堆栈的形式来组织的,遵循后进先出的原则。事实上,Task是一个非常复杂的概念,有兴趣的读者可以到官网http://developer.android.com/guide/topics/manifest/activity-element.html查看相关的资料。
4、ActivityRecord
5、TaskRecord ActivityRecor 中有成员变量类型为TaskRecord
实现原理
三者之间的关系
activity for result 的实现
问题:切换或者是退出Activity的时候闪出其他页面

startActivity() ->startActivityForResult() ->

Instrumentation.ActivityResult ar =            mInstrumentation.execStartActivity(                this, mMainThread.getApplicationThread(), mToken, who,                intent, requestCode, options);

上面的mMainThread是应用程序的主线程

在Instrumentation中的:
(Intrumentation用于监控系统和应用程序之间的交互)

 int result = ActivityManagerNative.getDefault()                .startActivity(whoThread, who.getBasePackageName(), intent,                        intent.resolveTypeIfNeeded(who.getContentResolver()),                        token, target != null ? target.mEmbeddedID : null,                        requestCode, 0, null, options);

ActivityManagerNative
ActivityManagerService
ActivityManagerProxy
IActivityManager

ActivityManagerProxy、ActivityManagerNative都实现了IActivityManager接口
ActivityManagerNative 继承了 Binder
ActivityManagerService 继承了 ActivityManagerNative

最终进行startActivity是在类ActivityManagerService中,

ActivityManagerService的startActivity()中

//mMainStack是ActivityStackmMainStack.startActivityMayWait(caller, intent, resolvedType,                grantedUriPermissions, grantedMode, resultTo, resultWho,                requestCode, onlyIfNeeded, debug, null, null);

ActivityStack中的startActivityMayWait()方法 调用了startActivityLocked()方法:

startActivityLocked(caller, intent, resolvedType,                    grantedUriPermissions, grantedMode, aInfo,                    resultTo, resultWho, requestCode, callingPid, callingUid,                    onlyIfNeeded, componentSpecified);

ActivityManagerService是管理Activity的生命周周期的。

每个应用程序都有一个ActivityThread来表示应用程序的主进程,每个ActivityThread都包含一个ApplicationThread实例

activity启动过程:
Step 1. 无论是通过Launcher来启动Activity,还是通过Activity内部调用startActivity接口来启动新的Activity,都通过Binder进程间通信进入到ActivityManagerService进程中,并且调用ActivityManagerService.startActivity接口;

Step 2. ActivityManagerService调用ActivityStack.startActivityMayWait来做准备要启动的Activity的相关信息;

Step 3. ActivityStack通知ApplicationThread要进行Activity启动调度了,这里的ApplicationThread代表的是调用ActivityManagerService.startActivity接口的进程,对于通过点击应用程序图标的情景来说,这个进程就是Launcher了,而对于通过在Activity内部调用startActivity的情景来说,这个进程就是这个Activity所在的进程了;

Step 4. ApplicationThread不执行真正的启动操作,它通过调用ActivityManagerService.activityPaused接口进入到ActivityManagerService进程中,看看是否需要创建新的进程来启动Activity;

Step 5. 对于通过点击应用程序图标来启动Activity的情景来说,ActivityManagerService在这一步中,会调用startProcessLocked来创建一个新的进程,而对于通过在Activity内部调用startActivity来启动新的Activity来说,这一步是不需要执行的,因为新的Activity就在原来的Activity所在的进程中进行启动;

Step 6. ActivityManagerServic调用ApplicationThread.scheduleLaunchActivity接口,通知相应的进程执行启动Activity的操作;

Step 7. ApplicationThread把这个启动Activity的操作转发给ActivityThread,ActivityThread通过ClassLoader导入相应的Activity类,然后把它启动起来。

这样,Android应用程序的Activity启动过程就简要介绍到这里了,在接下来的两篇文章中,我们将根据Activity的这两种启动情景,深入到应用程序框架层的源代码里面去,一步一步地分析它们的启动过程:


在方法ActivityStack.startActivityMayWait()方法中:

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;          // Don't modify the client's object!          intent = new Intent(intent);          // Collect information about the target of the Intent.          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) {              // Store the found target back into the intent, because now that              // we have it we never want to do this again.  For example, if the              // user navigates back to this point in the history, we should              // always restart the exact same activity.              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;          }      }      ......  }  

上面代码中:

 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) {              ......          }  

是将Intent中的信息解析出来得到Activity的相关信息保存在aInfo中

在方法startActivityLocked()中:

 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) {              ......          }          if (err == START_SUCCESS && intent.getComponent() == null) {              ......          }          if (err == START_SUCCESS && aInfo == null) {              ......          }          if (err != START_SUCCESS) {              ......          }          ......          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);      }  

sourceRecord = (ActivityRecord)mHistory.get(index);

 ActivityRecord r = new ActivityRecord(mService, this, callerApp, callingUid,                intent, resolvedType, aInfo, mService.mConfiguration,                resultRecord, resultWho, requestCode, componentSpecified);

即将要启动的Activity的相关信息,并保存在r变量中(r变量是ActivityRecord)
从参数caller得到调用者的进程信息,并保存在callApp中
参数resultTo是Launcher这个Activity里面的一个Binder对象,通过它可以获得Launcher这个Activity的相关信息,保存在sourceRecord变量中。


launcher也是一个Activity,
他的方法startActivitySafely():
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 会在一个新的task中加载Activity。

    // Refuse possible leaked file descriptors    if (intent != null && intent.hasFileDescriptors()) {        throw new IllegalArgumentException("File descriptors passed in Intent");    }    boolean componentSpecified = intent.getComponent() != null;    // Don't modify the client's object!    intent = new Intent(intent);    // Collect information about the target of the Intent.    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) {        aInfo = null;    }    if (aInfo != null) {        // Store the found target back into the intent, because now that        // we have it we never want to do this again.  For example, if the        // user navigates back to this point in the history, we should        // always restart the exact same activity.        intent.setComponent(new ComponentName(                aInfo.applicationInfo.packageName, aInfo.name));        // Don't debug things in the system process        if (debug) {            if (!aInfo.processName.equals("system")) {                mService.setDebugApp(aInfo.processName, true, false);            }        }    }    synchronized (mService) {        int callingPid;        int callingUid;        if (caller == null) {            callingPid = Binder.getCallingPid();            callingUid = Binder.getCallingUid();        } else {            callingPid = callingUid = -1;        }        mConfigWillChange = config != null                && mService.mConfiguration.diff(config) != 0;        if (DEBUG_CONFIGURATION) Slog.v(TAG,                "Starting activity when config will change = " + mConfigWillChange);        final long origId = Binder.clearCallingIdentity();        if (mMainStack && aInfo != null &&                (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {            // This may be a heavy-weight process!  Check to see if we already            // have another, different heavy-weight process running.            if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {                if (mService.mHeavyWeightProcess != null &&                        (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||                        !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {                    int realCallingPid = callingPid;                    int realCallingUid = callingUid;                    if (caller != null) {                        ProcessRecord callerApp = mService.getRecordForAppLocked(caller);                        if (callerApp != null) {                            realCallingPid = callerApp.pid;                            realCallingUid = callerApp.info.uid;                        } else {                            Slog.w(TAG, "Unable to find app for caller " + caller                                  + " (pid=" + realCallingPid + ") when starting: "                                  + intent.toString());                            return START_PERMISSION_DENIED;                        }                    }                    IIntentSender target = mService.getIntentSenderLocked(                            IActivityManager.INTENT_SENDER_ACTIVITY, "android",                            realCallingUid, null, null, 0, intent,                            resolvedType, PendingIntent.FLAG_CANCEL_CURRENT                            | PendingIntent.FLAG_ONE_SHOT);                    Intent newIntent = new Intent();                    if (requestCode >= 0) {                        // Caller is requesting a result.                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);                    }                    newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,                            new IntentSender(target));                    if (mService.mHeavyWeightProcess.activities.size() > 0) {                        ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,                                hist.packageName);                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,                                hist.task.taskId);                    }                    newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,                            aInfo.packageName);                    newIntent.setFlags(intent.getFlags());                    newIntent.setClassName("android",                            HeavyWeightSwitcherActivity.class.getName());                    intent = newIntent;                    resolvedType = null;                    caller = null;                    callingUid = Binder.getCallingUid();                    callingPid = Binder.getCallingPid();                    componentSpecified = true;                    try {                        ResolveInfo rInfo =                            AppGlobals.getPackageManager().resolveIntent(                                    intent, null,                                    PackageManager.MATCH_DEFAULT_ONLY                                    | ActivityManagerService.STOCK_PM_FLAGS);                        aInfo = rInfo != null ? rInfo.activityInfo : null;                    } catch (RemoteException e) {                        aInfo = null;                    }                }            }        }        int res = startActivityLocked(caller, intent, resolvedType,                grantedUriPermissions, grantedMode, aInfo,                resultTo, resultWho, requestCode, callingPid, callingUid,                onlyIfNeeded, componentSpecified);        if (mConfigWillChange && mMainStack) {            // If the caller also wants to switch to a new configuration,            // do so now.  This allows a clean switch, as we are waiting            // for the current activity to pause (so we will not destroy            // it), and have not yet started the next activity.            mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,                    "updateConfiguration()");            mConfigWillChange = false;            if (DEBUG_CONFIGURATION) Slog.v(TAG,                    "Updating to new configuration after starting activity.");            mService.updateConfigurationLocked(config, null);        }        Binder.restoreCallingIdentity(origId);        if (outResult != null) {            outResult.result = res;            if (res == IActivityManager.START_SUCCESS) {                mWaitingActivityLaunched.add(outResult);                do {                    try {                        mService.wait();                    } catch (InterruptedException e) {                    }                } while (!outResult.timeout && outResult.who == null);            } else if (res == IActivityManager.START_TASK_TO_FRONT) {                ActivityRecord r = this.topRunningActivityLocked(null);                if (r.nowVisible) {                    outResult.timeout = false;                    outResult.who = new ComponentName(r.info.packageName, r.info.name);                    outResult.totalTime = 0;                    outResult.thisTime = 0;                } else {                    outResult.thisTime = SystemClock.uptimeMillis();                    mWaitingActivityVisible.add(outResult);                    do {                        try {                            mService.wait();                        } catch (InterruptedException e) {                        }                    } while (!outResult.timeout && outResult.who == null);                }            }        }        return res;    }}//______________________________________________________________________________________________________________Binder对象的远程接口

要想将新的Activity在新的Task中打开,则必须设置intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),并且设置
这个Activity在Manifest.xml中的声明中添加了Task affinity,这个与之前的Activity所在栈的affinity不相同,才能在新的Task中打开新的Activity

adb dump 工具:adb shell dumpsys activity >c:\activity.txt :生成dump文件

0 0
原创粉丝点击