AMS分析--基于深入理解android(4)
2016-09-09 16:24
316 查看
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException { r.startFreezingScreenLocked(app, 0);//冻结屏幕 if (false) Slog.d(TAG, "realStartActivity: setting app visibility true"); mWindowManager.setAppVisibility(r.appToken, true);//设置app的r可见 // schedule launch ticks to collect information about slow apps. r.startLaunchTickingLocked();//打印启动日志 // Have the window manager re-evaluate the orientation of // the screen based on the new activity order. Note that // as a result of this, it can call back into the activity // manager with a new orientation. We don't care about that, // because the activity is not currently running so we are // just restarting it anyway. if (checkConfig) { Configuration config = mWindowManager.updateOrientationFromAppTokens( mService.mConfiguration, r.mayFreezeScreenLocked(app) ? r.appToken : null); //处理Config发生变化的情况 mService.updateConfigurationLocked(config, r, false, false); } r.app = app; app.waitingToKill = null; r.launchCount++; r.lastLaunchTime = SystemClock.uptimeMillis(); /// M: AMS log enhancement @{ if (localLOGV) Slog.v(TAG, "ACT-Launching: " + r); /// @} int idx = app.activities.indexOf(r); //将ActivityRecord加到ProcessRecord的activities中保存 if (idx < 0) { app.activities.add(r); } mService.updateLruProcessLocked(app, true, null); mService.updateOomAdjLocked(); //更新进程的调度优先级等,以后再分析该函数 final ActivityStack stack = r.task.stack; try { if (app.thread == null) { throw new RemoteException(); } List<ResultInfo> results = null; List<Intent> newIntents = null; if (andResume) { results = r.results; newIntents = r.newIntents; } if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r + " icicle=" + r.icicle + " with results=" + results + " newIntents=" + newIntents + " andResume=" + andResume); if (andResume) { EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY, r.userId, System.identityHashCode(r), r.task.taskId, r.shortComponentName); /// M: AMS log enhancement @{ if (!ActivityManagerService.IS_USER_BUILD) Slog.d(TAG, "ACT-AM_RESTART_ACTIVITY " + r + " Task:" + r.task.taskId); /// @} } if (r.isHomeActivity() && r.isNotResolverActivity()) {//是home程序且不是ResolverActivity // Home process is the root process of the task. mService.mHomeProcess = r.task.mActivities.get(0).app; } mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName()); ////对该APK做dex优化 r.sleeping = false; r.forceNewConfig = false; mService.showAskCompatModeDialogLocked(r); r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo); String profileFile = null; ParcelFileDescriptor profileFd = null; boolean profileAutoStop = false; if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) { if (mService.mProfileProc == null || mService.mProfileProc == app) { mService.mProfileProc = app; profileFile = mService.mProfileFile; profileFd = mService.mProfileFd; profileAutoStop = mService.mAutoStopProfiler; } } app.hasShownUi = true; app.pendingUiClean = true; if (profileFd != null) { try { profileFd = profileFd.dup(); } catch (IOException e) { if (profileFd != null) { try { profileFd.close(); } catch (IOException o) { } profileFd = null; } } } app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_TOP);//设置进程为当前Activity所属进程所有者 mService.logAppLaunchTime(TAG, "scheduleLaunchActivity -> ActivityThread"); /// M: It's for debugging App Launch time //通知应用进程启动Activity app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken, System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration), r.compat, app.repProcState, r.icicle, results, newIntents, !andResume, mService.isNextTransitionForward(), profileFile, profileFd, profileAutoStop); if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) { // This may be a heavy-weight process! Note that the package // manager will ensure that only activity can run in the main // process of the .apk, which is the only thing that will be // considered heavy-weight. if (app.processName.equals(app.info.packageName)) { if (mService.mHeavyWeightProcess != null && mService.mHeavyWeightProcess != app) { Slog.w(TAG, "Starting new heavy weight process " + app + " when already running " + mService.mHeavyWeightProcess); } mService.mHeavyWeightProcess = app; Message msg = mService.mHandler.obtainMessage( ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG); msg.obj = r; mService.mHandler.sendMessage(msg); } } } catch (RemoteException e) { if (r.launchFailed) { // This is the second time we failed -- finish activity // and give up. Slog.e(TAG, "Second failure launching " + r.intent.getComponent().flattenToShortString() + ", giving up", e); mService.appDiedLocked(app, app.pid, app.thread); stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null, "2nd-crash", false); return false; } /// M: fix google issue, add to prevent process starting repeatly /// If AP is in 2nd crash, we will stop trying to start AP process. @{ r.launchFailed = true; /// @} // This is the first time we failed -- restart process and // retry. app.activities.remove(r); throw e; } r.launchFailed = false; if (stack.updateLRUListLocked(r)) {//更新oodm 进程优先级 Slog.w(TAG, "Activity " + r + " being launched, but already in LRU list"); } if (andResume) { // As part of the process of launching, ActivityThread also performs // a resume. stack.minimalResumeActivityLocked(r);//完成 Activity 启动 } else { // This activity is not starting in the resumed state... which // should look like we asked it to pause+stop (but remain visible), // and it has done so and reported back the current icicle and // other state. if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r + " (starting in stopped state)"); r.state = ActivityState.STOPPED; r.stopped = true; } // Launch the new version setup screen if needed. We do this -after- // launching the initial activity (that is, home), so that it can have // a chance to initialize itself while in the background, making the // switch back to it faster and look better. if (isFrontStack(stack)) { mService.startSetupActivityLocked();//是否更新 ui显示 } return true; }
调用 ProcessRecord.thread ( ActivityThread 类型)的 scheduleLaunchActivity() 通知应用的主进程启动 Activity :
AMS通过realStartActivityLocked函数来调度应用程序进程启动一个Activity,参数r为即将启动的Activity在AMS服务中的描述符,参数app为Activity运行所在的应用程序进程在AMS服务中的描述符。函数通过IApplicationThread代理对象ApplicationThreadProxy通知应用程序进程启动r对应的Activity,应用程序进程完成Activity的加载等准备工作后,AMS最后启动该Activity。启动Activity的创建等工作是在应用程序进程中完成的,AMS是通过IApplicationThread接口和应用程序进程通信的。r.appToken 在AMS服务端的类型为Token,是IApplicationToken的Binder本地对象。
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo, int procState, Bundle state, List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, boolean notResumed, boolean isForward, String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) { updateProcessState(procState, false); ActivityClientRecord r = new ActivityClientRecord(); r.token = token; r.ident = ident; r.intent = intent; r.activityInfo = info; r.compatInfo = compatInfo; r.state = state; r.pendingResults = pendingResults; r.pendingIntents = pendingNewIntents; r.startsNotResumed = notResumed; r.isForward = isForward; r.profileFile = profileName; r.profileFd = profileFd; r.autoStopProfiler = autoStopProfiler; updatePendingConfiguration(curConfig); sendMessage(H.LAUNCH_ACTIVITY, r); }
参数token从AMS服务端经过Binder传输到应用程序进程后,变为IApplicationToken的Binder代理对象,类型为IApplicationToken.Proxy,这是因为AMS和应用程序运行在不同的进程中。
通过queueOrSendMessage函数将Binder跨进程调用转换为应用程序进程中的异步消息处理
上述代码最后调用到
public void handleMessage(Message msg) { ...... switch (msg.what) { case LAUNCH_ACTIVITY: { ActivityClientRecord r = (ActivityClientRecord)msg.obj; //ActivityClientRecord 代表着在应用进程中的一个Activity r.packageInfo = getPackageInfoNoCheck( r.activityInfo.applicationInfo, r.compatInfo); handleLaunchActivity(r, null); }
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo) ->
getPackageInfo(ai, compatInfo, null, false, true) ->
new LoadedApk(this, aInfo, compatInfo, this, baseLoader,
securityViolation, includeCode &&
(aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0)
获得当前 Activity的LoadedApk对象。
public LoadedApk(ActivityThread activityThread, String name, Context systemContext, ApplicationInfo info, CompatibilityInfo compatInfo) { mActivityThread = activityThread; mApplicationInfo = info != null ? info : new ApplicationInfo(); mApplicationInfo.packageName = name; mPackageName = name; mAppDir = null; mResDir = null; mSharedLibraries = null; mDataDir = null; mDataDirFile = null; mLibDir = null; mBaseClassLoader = null; mSecurityViolation = false; mIncludeCode = true; mClassLoader = systemContext.getClassLoader(); mResources = systemContext.getResources(); mDisplayAdjustments.setCompatibilityInfo(compatInfo); }
LoadedApk类记录了Activity运行所在的ActivityThread、Activity所在的应用程序信息、Activity的包名、Activity的资源路径、Activity的库路径、Activity的数据存储路径、类加载器和应用程序所使用的资源等信息
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")"); ActivityInfo aInfo = r.activityInfo; if (r.packageInfo == null) { //如果 LoadedApk 为null,重新获取LoadedApk r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo, Context.CONTEXT_INCLUDE_CODE); } ComponentName component = r.intent.getComponent();//获取Activity的 ComponentName if (component == null) { component = r.intent.resolveActivity( mInitialApplication.getPackageManager()); r.intent.setComponent(component); } if (r.activityInfo.targetActivity != null) { //packageName为启动Activity的包名,targetActivity为Activity的类名 component = new ComponentName(r.activityInfo.packageName, r.activityInfo.targetActivity); } Activity activity = null; try { //通过类反射方式加载即将启动的Activity //利用Class loader和ComponentName对象搭配 //mInstrumentation.newActivity函数产生一个新的activity对象. java.lang.ClassLoader cl = r.packageInfo.getClassLoader(); activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); StrictMode.incrementExpectedActivityCount(activity.getClass()); r.intent.setExtrasClassLoader(cl); if (r.state != null) { r.state.setClassLoader(cl); } } catch (Exception e) { if (!mInstrumentation.onException(activity, e)) { throw new RuntimeException( "Unable to instantiate activity " + component + ": " + e.toString(), e); } } try { //通过单例模式为应用程序进程创建Application对象 Application app = r.packageInfo.makeApplication(false, mInstrumentation); if (localLOGV) Slog.v(TAG, "Performing launch of " + r); if (localLOGV || mIsUserBuild) Slog.v( TAG, r + ": app=" + app + ", appName=" + app.getPackageName() + ", pkg=" + r.packageInfo.getPackageName() + ", comp=" + r.intent.getComponent().toShortString() + ", dir=" + r.packageInfo.getAppDir()); if (activity != null) { //为当前Activity创建上下文对象ContextImpl Context appContext = createBaseContextForActivity(r, activity); CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager()); Configuration config = new Configuration(mCompatConfiguration); if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity " + r.activityInfo.name + " with config " + config); //将当前启动的Activity和上下文ContextImpl、Application绑定 activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config); if (customIntent != null) { activity.mIntent = customIntent; } //设定activity的参数intent设定跟背景主题设定 r.lastNonConfigurationInstances = null; activity.mStartedActivity = false; int theme = r.activityInfo.getThemeResource(); if (theme != 0) { activity.setTheme(theme); } activity.mCalled = false; //调用Activity的OnCreate函数 mInstrumentation.callActivityOnCreate(activity, r.state); if (!activity.mCalled) { throw new SuperNotCalledException( "Activity " + r.intent.getComponent().toShortString() + " did not call through to super.onCreate()"); } //将Activity保存到ActivityClientRecord中,ActivityClientRecord为Activity在应用程序进程中的描述符 r.activity = activity; r.stopped = true; if (!r.activity.mFinished) { activity.performStart(); r.stopped = false; } if (!r.activity.mFinished) {//mFinished 表示 if (r.state != null) { //在activity被杀掉之前调用保存每个实例的状态,以保证该状态可以在onCreate(Bundle)或者onRestoreInstanceState(Bundle) //(传入的Bundle参数是由onSaveInstanceState封装好的)中恢复。这个方法在一个activity被杀死前调用 //,当该activity在将来某个时刻回来时可以恢复其先前状态。 //最终会调用onRestoreInstanceState 方法 ,将 activity恢复其先前状态 mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state); } } if (!r.activity.mFinished) { activity.mCalled = false; mInstrumentation.callActivityOnPostCreate(activity, r.state); if (!activity.mCalled) { throw new SuperNotCalledException( "Activity " + r.intent.getComponent().toShortString() + " did not call through to super.onPostCreate()"); } } } r.paused = true; //ActivityThread的成员变量mActivities保存了当前应用程序进程中的所有Activity的描述符 mActivities.put(r.token, r); mActivities.put(r.token, r); } catch (SuperNotCalledException e) { throw e; } catch (Exception e) { if (!mInstrumentation.onException(activity, e)) { throw new RuntimeException( "Unable to start activity " + component + ": " + e.toString(), e); } } return activity; }
在该函数中,首先通过PMS服务查找到即将启动的Activity的包名信息,然后通过类反射方式创建一个该Activity实例,同时为应用程序启动的每一个Activity创建一个LoadedApk实例对象,应用程序进程中创建的所有LoadedApk对象保存在ActivityThread的成员变量mPackages中。接着通过LoadedApk对象的makeApplication函数,使用单例模式创建Application对象,因此在android应用程序进程中有且只有一个Application实例。然后为当前启动的Activity创建一个ContextImpl上下文对象,并初始化该上下文,到此我们可以知道,启动一个Activity需要以下对象:
1) XXActivity对象,需要启动的Activity;
2) LoadedApk对象,每个启动的Activity都拥有属于自身的LoadedApk对象;
3) ContextImpl对象,每个启动的Activity都拥有属于自身的ContextImpl对象;
4) Application对象,应用程序进程中有且只有一个实例,和Activity是一对多的关系;
public final ActivityClientRecord performResumeActivity(IBinder token, boolean clearHide) { ActivityClientRecord r = mActivities.get(token);//找出当前要启动的Activities if (localLOGV || mIsUserBuild) Slog.v(TAG, "Performing resume of " + r + " finished=" + ((r != null && r.activity != null) ? r.activity.mFinished : null)); if (r != null && !r.activity.mFinished) { if (clearHide) { r.hideForNow = false; r.activity.mStartedActivity = false; } try { r.activity.mFragments.noteStateNotSaved(); if (r.pendingIntents != null) { deliverNewIntents(r, r.pendingIntents);//当在singleTask 或者singleTop模式下,系统中只会存在一个 //Activity实例,所以当我们要启动这个实例的时候,如果发现系统中已经存在activity,就会执行onNewIntent r.pendingIntents = null; } if (r.pendingResults != null) { deliverResults(r, r.pendingResults); r.pendingResults = null; } r.activity.performResume(); //会先执行 performRestart -> activity.onRestart() // 接着 -> callActivityOnResume-> activity.onResume EventLog.writeEvent(LOG_ON_RESUME_CALLED, UserHandle.myUserId(), r.activity.getComponentName().getClassName()); /// M: ActivityThread log enhancement @{ if(!mIsUserBuild) Slog.d(TAG, "ACT-AM_ON_RESUME_CALLED " + r); /// @} r.paused = false; r.stopped = false; r.state = null; } catch (Exception e) { if (!mInstrumentation.onException(r.activity, e)) { throw new RuntimeException( "Unable to resume activity " + r.intent.getComponent().toShortString() + ": " + e.toString(), e); } } } return r; }
调用activity.performResume()方法,在activity.performResume()中会默认先调用performRestart(),performRestart()的作用是先检查activity是否处于stopped状态,如果是则调用performRestart()再调用performStart()。最后再响应activity的生命周期方法onResume()。
所以,新打开一个activity的响应流程是:
onCreate()->onStart()->onResume()
而返回一个后台activity的响应流程是:
onRestart()->onStart()->onResume()
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume) { if (r.window == null && !a.mFinished && willBeVisible) { //获得为当前Activity创建的窗口PhoneWindow对象 r.window = r.activity.getWindow(); //获取为窗口创建的视图DecorView对象 View decor = r.window.getDecorView(); decor.setVisibility(View.INVISIBLE); //在attach函数中就为当前Activity创建了WindowManager对象 ViewManager wm = a.getWindowManager(); WindowManager.LayoutParams l = r.window.getAttributes(); //得到该视图对象的布局参数 a.mDecor = decor; l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION; l.softInputMode |= forwardBit; if (a.mVisibleFromClient) { a.mWindowAdded = true; //将创建的视图对象DecorView添加到Activity的窗口管理器中 wm.addView(decor, l); } ...... if (r.activity.mVisibleFromClient) { ViewManager wm = a.getWindowManager(); View decor = r.window.getDecorView(); wm.updateViewLayout(decor, l); //将当前Activity的视图显示出来 } ... Looper.myQueue().addIdleHandler(new Idler()); //一是调用方法finishUserBoot()把状态还是STATE_BOOTING的用户切换到STATE_RUNNING状态 //,同时发送广播ACTION_BOOT_COMPLETED给该用户,表示用户启动结束。另一件工作是停止多余的用户
final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout, Configuration config) { if (localLOGV) Slog.v(TAG, "Activity idle: " + token); /// M: PerfBoost @{ if (mIsPerfBoostEnable) { PerfService.nativePerfBoostDisable(PerfService.SCN_APP_SWITCH); mIsPerfBoostEnable = false; } /// @} ArrayList<ActivityRecord> stops = null; ArrayList<ActivityRecord> finishes = null; ArrayList<UserStartedState> startingUsers = null; int NS = 0; int NF = 0; IApplicationThread sendThumbnail = null; boolean booting = false; boolean enableScreen = false; boolean activityRemoved = false; ActivityRecord r = ActivityRecord.forToken(token);//找到当前的 ActivityRecord if (r != null) { if (DEBUG_IDLE) Slog.d(TAG, "activityIdleInternalLocked: Callers=" + Debug.getCallers(4)); mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);//移除IDLE_TIMEOUT_MSG 消息 r.finishLaunchTickingLocked(); if (fromTimeout) { reportActivityLaunchedLocked(fromTimeout, r, -1, -1); } // This is a hack to semi-deal with a race condition // in the client where it can be constructed with a // newer configuration from when we asked it to launch. // We'll update with whatever configuration it now says // it used to launch. if (config != null) { r.configuration = config; } // We are now idle. If someone is waiting for a thumbnail from // us, we can now deliver. r.idle = true;//当前我们已经进入idle模式。并且已经移除IDLE_TIMEOUT_MSG,所以为 true if (r.thumbnailNeeded && r.app != null && r.app.thread != null) { sendThumbnail = r.app.thread; r.thumbnailNeeded = false; } //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout); if (!mService.mBooted && isFrontStack(r.task.stack)) { mService.mBooted = true; enableScreen = true; } } if (allResumedActivitiesIdle()) {//所以此处 内部我们判断r.idle为true if (r != null) { mService.scheduleAppGcsLocked();//知所有进行中的任务进行垃圾回收 } /* mLaunchingActivity是一个WakeLock,它能防止在操作Activity过程中掉电,同时 这个WakeLock又不能长时间使用,否则有可能耗费过多电量。所以,系统设置了一个超时 处理消息LAUNCH_TIMEOUT_MSG,超时时间为10秒。一旦目标Activity启动成功, 就需要需要释放 WakeLock */ if (mLaunchingActivity.isHeld()) { mHandler.removeMessages(LAUNCH_TIMEOUT_MSG); if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) { throw new IllegalStateException("Calling must be system uid"); } mLaunchingActivity.release(); } ensureActivitiesVisibleLocked(null, 0); } // Atomically retrieve all of the other things to do. stops = processStoppingActivitiesLocked(true);// 得到因本次启动而被 pause 的 Activity NS = stops != null ? stops.size() : 0; if ((NF=mFinishingActivities.size()) > 0) { finishes = new ArrayList<ActivityRecord>(mFinishingActivities); mFinishingActivities.clear(); } final ArrayList<ActivityRecord> thumbnails; final int NT = mCancelledThumbnails.size(); if (NT > 0) { thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails); mCancelledThumbnails.clear(); } else { thumbnails = null; } if (isFrontStack(mHomeStack)) { booting = mService.mBooting; mService.mBooting = false; } if (mStartingUsers.size() > 0) { startingUsers = new ArrayList<UserStartedState>(mStartingUsers); mStartingUsers.clear(); } // Perform the following actions from unsynchronized state. final IApplicationThread thumbnailThread = sendThumbnail; mHandler.post(new Runnable() { @Override public void run() { if (thumbnailThread != null) { try { thumbnailThread.requestThumbnail(token); } catch (Exception e) { Slog.w(TAG, "Exception thrown when requesting thumbnail", e); mService.sendPendingThumbnail(null, token, null, null, true); } } // Report back to any thumbnail receivers. for (int i = 0; i < NT; i++) { ActivityRecord r = thumbnails.get(i); mService.sendPendingThumbnail(r, null, null, null, true); } } }); // Stop any activities that are scheduled to do so but have been // waiting for the next one to start. for (int i = 0; i < NS; i++) { r = stops.get(i); final ActivityStack stack = r.task.stack; if (r.finishing) { stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false); // 如果被暂停的Activity处于finishing状态(例如Activity在其onStop中调用了finish函数),则调用finishCurrentActivityLocked } else { stack.stopActivityLocked(r); } } // Finish any activities that are scheduled to do so but have been // waiting for the next one to start. for (int i = 0; i < NF; i++) { r = finishes.get(i); activityRemoved |= r.task.stack.destroyActivityLocked(r, true, false, "finish-idle"); } if (booting) {//如果是系统开机启动桌面。此时启动完成发广播 ACTION_BOOT_COMPLETED mService.finishBooting(); } else if (startingUsers != null) { for (int i = 0; i < startingUsers.size(); i++) { mService.finishUserSwitch(startingUsers.get(i)); } } mService.trimApplications(); //dump(); //mWindowManager.dump(); if (enableScreen) { mService.enableScreenAfterBoot(); } if (activityRemoved) { resumeTopActivitiesLocked(); } return r; }
在startPausingLocked()时会将要paused的ActivityRecord保存在mPausingActivity中,当pause成功后会调用activityPausedLocked()函数做后续处理,在这个函数中会将mPausingActivity重置为null
final void startPausingLocked(boolean userLeaving, boolean uiSleeping) { if (mPausingActivity != null) { //如果要pause一个Activity时,已经有一个Activity在pause还未完成 //(pause完成的话mPausingActivity 为null),那么抛出一个异常。 Slog.e(TAG, "Trying to pause when pause is already pending for " + mPausingActivity, new RuntimeException("here").fillInStackTrace()); } ActivityRecord prev = mResumedActivity;//保存正在显示的app //mResumedActivity中保存的是当前resume的Activity, // pause的对象肯定是当前的resume的Activity,如果当前没有resume对象, //这种情况也就是系统启动第一个Activity才有的情况,此时就直接resume Activity栈中的顶层Activity。 if (prev == null) { Slog.e(TAG, "Trying to pause when nothing is resumed", new RuntimeException("here").fillInStackTrace()); mStackSupervisor.resumeTopActivitiesLocked(); return; } if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSING: " + prev); else if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev); //当前resume的Activity要被pause掉了,那么mResumedActivity必然要重置为null了? // 同时mPausingActivity指向当前resumed的Activity。 mResumedActivity = null; mPausingActivity = prev; mLastPausedActivity = prev; mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0 || (prev.info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0 ? prev : null; prev.state = ActivityState.PAUSING; prev.task.touchActiveTime(); clearLaunchTime(prev); /// M: Add for launch time enhancement @{ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "amScreenCapture"); if (!prev.isHomeActivity()) { prev.updateThumbnail(screenshotActivities(prev), null); } Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); /// @} stopFullyDrawnTraceIfNeeded(); mService.updateCpuStats(); if (prev.app != null && prev.app.thread != null) { if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev); try { EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY, prev.userId, System.identityHashCode(prev), prev.shortComponentName); /// M: AMS log enhancement @{ if (!ActivityManagerService.IS_USER_BUILD) Slog.d(TAG, "ACT-AM_PAUSE_ACTIVITY " + prev ); /// @} mService.updateUsageStats(prev, false); //调用当前Activity所在进程的schedulePauseActivity函数 prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing, userLeaving, prev.configChangeFlags); } catch (Exception e) { // Ignore exception, if process died other code will cleanup. Slog.w(TAG, "Exception thrown during pause", e); mPausingActivity = null; mLastPausedActivity = null; mLastNoHistoryActivity = null; } } else { mPausingActivity = null; mLastPausedActivity = null; mLastNoHistoryActivity = null; } // If we are not going to sleep, we want to ensure the device is // awake until the next activity is started. if (!mService.isSleepingOrShuttingDown()) { mStackSupervisor.acquireLaunchWakelock(); //获取一个唤醒锁,防止系统睡眠,获取唤醒锁时要注意释放 } if (mPausingActivity != null) { // Have the window manager pause its key dispatching until the new // activity has started. If we're pausing the activity just because // the screen is being turned off and the UI is sleeping, don't interrupt // key dispatch; the same activity will pick it up again on wakeup. if (!uiSleeping) { prev.pauseKeyDispatchingLocked();//暂停按键下发通道,直到新的activity起来 } else { if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off"); } // Schedule a pause timeout in case the app doesn't respond. // We don't give it much time because this directly impacts the // responsiveness seen by the user. Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG); msg.obj = prev; prev.pauseTime = SystemClock.uptimeMillis(); mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT); //设置超时500ms,告诉应用尽快完成相关操作 //⑨post一个PAUSE_TIMEOUT_MSG消息,为什么要post这么个消息 //,是因为如果无法完成paused前一个Activity,那么就无法start下一个Activity //,这个超时消息是防止异常导致无法及时start下一个Activity,在超时消息处理函数中肯定有start next Activity的逻辑。 if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete..."); } else { // This activity failed to schedule the // pause, so just treat it as being paused now. if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next."); mStackSupervisor.getFocusedStack().resumeTopActivityLocked(null); } }
startPausingLocked将调用应用进程的schedulePauseActivity函数,并设置500毫秒的超时时间,所以应用进程需尽快完成相关处理。和scheduleLaunchActivity一样,schedulePauseActivity将向ActivityThread主线程发送PAUSE_ACTIVITY消息,最终该消息由handlePauseActivity来处理。
private void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges) { ActivityClientRecord r = mActivities.get(token); if (r != null) { //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r); if (userLeaving) { performUserLeavingActivity(r);//告诉用户要离开当前activity,会调用onUserLeaveHint函数 } r.activity.mConfigChangeFlags |= configChanges; performPauseActivity(token, finished, r.isPreHoneycomb()); //调用Activity的onPause函数 // Make sure any pending writes are now committed. if (r.isPreHoneycomb()) { QueuedWork.waitToFinish(); } // Tell the activity manager we have paused. try { ActivityManagerNative.getDefault().activityPaused(token); } catch (RemoteException ex) { } } }
final void activityPausedLocked(IBinder token, boolean timeout) { if (DEBUG_PAUSE) Slog.v( TAG, "Activity paused: token=" + token + ", timeout=" + timeout); /// M: AMS log enhancement @{ if (!ActivityManagerService.IS_USER_BUILD) Slog.d(TAG, "ACT-paused: token=" + token + ", timeout=" + timeout); /// @} final ActivityRecord r = isInStackLocked(token); if (r != null) { //从消息队列中撤销PAUSE_TIMEOUT_MSG消息 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r); if (mPausingActivity == r) { if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSED: " + r + (timeout ? " (due to timeout)" : " (pause complete)")); r.state = ActivityState.PAUSED;//设置 ActivityRecord 状态 completePauseLocked();//完成本次 暂停
private void completePauseLocked() { ActivityRecord prev = mPausingActivity; if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev); if (prev != null) { if (prev.finishing) { if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev); prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false);//结束这个 ActivityRecord } else if (prev.app != null) { if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev); if (prev.waitingVisible) { prev.waitingVisible = false;//因为此Activity要暂停,所以不在等待可见。只有要显示Activity 的waitingVisible为true mStackSupervisor.mWaitingVisibleActivities.remove(prev); if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v( TAG, "Complete pause, no longer waiting: " + prev); } if (prev.configDestroy) { destroyActivityLocked(prev, true, false, "pause-config"); } else { mStackSupervisor.mStoppingActivities.add(prev); if (mStackSupervisor.mStoppingActivities.size() > 3 || prev.frontOfTask && mTaskHistory.size() <= 1) { if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle"); mStackSupervisor.scheduleIdleLocked(); //如果被暂停的activity超过3个或者 当前activity是root activity且当前task是最后一个task if (!ActivityManagerService.IS_USER_BUILD) Slog.d(TAG, "ACT-IDLE_NOW_MSG from completePauseLocked for mStoppingActivities.size() > 3"); /// @} } else { mStackSupervisor.checkReadyForSleepLocked(); } } } else { if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev); prev = null; } mPausingActivity = null; } final ActivityStack topStack = mStackSupervisor.getFocusedStack(); if (!mService.isSleepingOrShuttingDown()) {//如果系统不是在将要睡眠和关闭 mStackSupervisor.resumeTopActivitiesLocked(topStack, prev, null);//启动在栈顶的Activity } else { mStackSupervisor.checkReadyForSleepLocked(); ActivityRecord top = topStack.topRunningActivityLocked(null);//启动在栈顶的Activity if (top == null || (prev != null && top != prev)) { mStackSupervisor.resumeTopActivitiesLocked(topStack, null, null); } } if (prev != null) { /// M: it's to avoid deadlock in AMS/WMS, Ref: ALPS00231742 @{ //prev.resumeKeyDispatchingLocked(); new myThread(prev).start(); /// @} if (prev.app != null && prev.cpuTimeAtResume > 0 && mService.mBatteryStatsService.isOnBattery()) { long diff; synchronized (mService.mProcessCpuThread) { diff = mService.mProcessCpuTracker.getCpuTimeForPid(prev.app.pid) - prev.cpuTimeAtResume; } if (diff > 0) { BatteryStatsImpl bsi = mService.mBatteryStatsService.getActiveStatistics(); synchronized (bsi) { BatteryStatsImpl.Uid.Proc ps = bsi.getProcessStatsLocked(prev.info.applicationInfo.uid, prev.info.packageName); if (ps != null) { ps.addForegroundTimeLocked(diff); } } } } prev.cpuTimeAtResume = 0; // reset it } }
相关文章推荐
- AMS分析--基于深入理解android(3)
- AMS分析--基于深入理解android(1)
- AMS分析--基于深入理解android(2)
- AMS—启动一个Activity(基于深入理解Android)
- 深入理解init_1----init分析(基于Android 2.2,源码来自Google)
- Android LayoutInflater原理分析,深入理解View(一)
- 深入理解Android内核——Android启动分析
- Android 基础功 - activity启动模式深入理解分析
- 【Android 开发】深入理解内存缓存类LruCache:源码分析
- 深入理解init_5-----属性服务(基于Android 2.2,代码源自Google)
- 深入理解Android事件分发机制之源码分析
- Android一步步深入理解View(一):LayoutInflater的使用和原理分析
- Cubietruck---13.sp与wp分析_深入理解android第五章笔记
- 深入理解Android(5)——从MediaScanner分析Android中的JNI
- Android源码分析-深入理解setContentView方法
- 深入理解init_4``````````init控制service(基于Android2.2,代码源自Google)
- 深入理解init_2-----解析配置文件init.rc(基于Android 2.2,代码源于Google)
- Cubietruck---14. binder分析_深入理解android第六章笔记
- 深入理解Spark ML:基于ALS矩阵分解的协同过滤算法与源码分析
- 【Android开发】深入理解硬盘缓存类DiskLruCache:源码分析