Loading services/java/com/android/server/am/ActivityManagerService.java +19 −9 Original line number Diff line number Diff line Loading @@ -1466,7 +1466,7 @@ public final class ActivityManagerService extends ActivityManagerNative m.mFactoryTest = factoryTest; m.mStackSupervisor = new ActivityStackSupervisor(m, context, thr.mLooper); m.mStackSupervisor.init(); m.mStackSupervisor.init(m.mCurrentUserId); m.mBatteryStatsService.publish(context); m.mUsageStatsService.publish(context); Loading Loading @@ -1886,6 +1886,13 @@ public final class ActivityManagerService extends ActivityManagerNative mHandler.obtainMessage(IMMERSIVE_MODE_LOCK_MSG, (nextState) ? 1 : 0, 0, r)); } final void showAskCompatModeDialogLocked(ActivityRecord r) { Message msg = Message.obtain(); msg.what = SHOW_COMPAT_MODE_DIALOG_MSG; msg.obj = r.task.askedCompatMode ? null : r; mHandler.sendMessage(msg); } private final void updateLruProcessInternalLocked(ProcessRecord app, int bestPos) { // put it on the LRU to keep track of when it should be exited. int lrui = mLruProcesses.indexOf(app); Loading Loading @@ -3491,6 +3498,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } @Override public boolean clearApplicationUserData(final String packageName, final IPackageDataObserver observer, int userId) { enforceNotIsolatedCaller("clearApplicationUserData"); Loading Loading @@ -3546,6 +3554,7 @@ public final class ActivityManagerService extends ActivityManagerNative return true; } @Override public void killBackgroundProcesses(final String packageName, int userId) { if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES) != PackageManager.PERMISSION_GRANTED && Loading Loading @@ -3582,6 +3591,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } @Override public void killAllBackgroundProcesses() { if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES) != PackageManager.PERMISSION_GRANTED) { Loading services/java/com/android/server/am/ActivityStack.java +23 −197 Original line number Diff line number Diff line Loading @@ -42,7 +42,6 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.content.res.Resources; Loading @@ -54,18 +53,15 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.PowerManager; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.util.EventLog; import android.util.Log; import android.util.Slog; import android.view.Display; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.util.ArrayList; Loading @@ -88,10 +84,10 @@ final class ActivityStack { static final boolean DEBUG_TASKS = ActivityManagerService.DEBUG_TASKS; static final boolean DEBUG_CLEANUP = ActivityManagerService.DEBUG_CLEANUP; static final boolean DEBUG_STATES = false; static final boolean DEBUG_ADD_REMOVE = false; static final boolean DEBUG_SAVED_STATE = false; static final boolean DEBUG_APP = false; static final boolean DEBUG_STATES = ActivityStackSupervisor.DEBUG_STATES; static final boolean DEBUG_ADD_REMOVE = ActivityStackSupervisor.DEBUG_ADD_REMOVE; static final boolean DEBUG_SAVED_STATE = ActivityStackSupervisor.DEBUG_SAVED_STATE; static final boolean DEBUG_APP = ActivityStackSupervisor.DEBUG_APP; static final boolean VALIDATE_TOKENS = ActivityManagerService.VALIDATE_TOKENS; Loading Loading @@ -445,7 +441,7 @@ final class ActivityStack { } ActivityStack(ActivityManagerService service, Context context, Looper looper, int stackId, ActivityStackSupervisor supervisor) { ActivityStackSupervisor supervisor, int userId) { mHandler = new ActivityStackHandler(looper); mService = service; mContext = context; Loading @@ -456,6 +452,7 @@ final class ActivityStack { mLaunchingActivity.setReferenceCounted(false); mStackId = stackId; mStackSupervisor = supervisor; mCurrentUser = userId; } private boolean okToShow(ActivityRecord r) { Loading Loading @@ -541,7 +538,7 @@ final class ActivityStack { return null; } private final boolean updateLRUListLocked(ActivityRecord r) { final boolean updateLRUListLocked(ActivityRecord r) { final boolean hadit = mLRUActivities.remove(r); mLRUActivities.add(r); return hadit; Loading Loading @@ -619,13 +616,6 @@ final class ActivityStack { return null; } final void showAskCompatModeDialogLocked(ActivityRecord r) { Message msg = Message.obtain(); msg.what = ActivityManagerService.SHOW_COMPAT_MODE_DIALOG_MSG; msg.obj = r.task.askedCompatMode ? null : r; mService.mHandler.sendMessage(msg); } /* * Move the activities around in the stack to bring a user to the foreground. * @return whether there are any activities for the specified user. Loading Loading @@ -660,150 +650,7 @@ final class ActivityStack { return haveActivities; } final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException { r.startFreezingScreenLocked(app, 0); mService.mWindowManager.setAppVisibility(r.appToken, true); // 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 = mService.mWindowManager.updateOrientationFromAppTokens( mService.mConfiguration, r.mayFreezeScreenLocked(app) ? r.appToken : null); mService.updateConfigurationLocked(config, r, false, false); } r.app = app; app.waitingToKill = null; r.launchCount++; r.lastLaunchTime = SystemClock.uptimeMillis(); if (localLOGV) Slog.v(TAG, "Launching: " + r); int idx = app.activities.indexOf(r); if (idx < 0) { app.activities.add(r); } mService.updateLruProcessLocked(app, true); 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); } if (r.isHomeActivity) { mService.mHomeProcess = app; } mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName()); r.sleeping = false; r.forceNewConfig = false; 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.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken, System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration), r.compat, 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) { Log.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); requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null, "2nd-crash", false); return false; } // This is the first time we failed -- restart process and // retry. app.activities.remove(r); throw e; } r.launchFailed = false; if (updateLRUListLocked(r)) { 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. void minimalResumeActivityLocked(ActivityRecord r) { r.state = ActivityState.RESUMED; if (DEBUG_STATES) Slog.v(TAG, "Moving to RESUMED: " + r + " (starting new instance)"); Loading @@ -814,26 +661,6 @@ final class ActivityStack { completeResumeLocked(r); checkReadyForSleepLocked(); if (DEBUG_SAVED_STATE) Slog.i(TAG, "Launch completed; removing icicle of " + r.icicle); } 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 (mStackSupervisor.isMainStack(this)) { mService.startSetupActivityLocked(); } return true; } private final void startSpecificActivityLocked(ActivityRecord r, Loading @@ -854,7 +681,7 @@ final class ActivityStack { if (app != null && app.thread != null) { try { app.addPackage(r.info.packageName); realStartActivityLocked(r, app, andResume, checkConfig); mStackSupervisor.realStartActivityLocked(r, app, andResume, checkConfig); return; } catch (RemoteException e) { Slog.w(TAG, "Exception when starting activity " Loading Loading @@ -1749,7 +1576,7 @@ final class ActivityStack { next.task.taskId, next.shortComponentName); next.sleeping = false; showAskCompatModeDialogLocked(next); mService.showAskCompatModeDialogLocked(next); next.app.pendingUiClean = true; next.app.thread.scheduleResumeActivity(next.appToken, mService.isNextTransitionForward()); Loading Loading @@ -3429,7 +3256,6 @@ final class ActivityStack { private static final int FINISH_AFTER_PAUSE = 1; private static final int FINISH_AFTER_VISIBLE = 2; private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj) { // First things first: if this activity is currently visible, Loading services/java/com/android/server/am/ActivityStackSupervisor.java +189 −4 Original line number Diff line number Diff line Loading @@ -16,11 +16,14 @@ package com.android.server.am; import static com.android.server.am.ActivityManagerService.localLOGV; import static com.android.server.am.ActivityManagerService.DEBUG_CLEANUP; import static com.android.server.am.ActivityManagerService.DEBUG_CONFIGURATION; import static com.android.server.am.ActivityManagerService.DEBUG_PAUSE; import static com.android.server.am.ActivityManagerService.DEBUG_SWITCH; import static com.android.server.am.ActivityManagerService.TAG; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.AppGlobals; Loading @@ -29,6 +32,7 @@ import android.app.IThumbnailReceiver; import android.app.PendingIntent; import android.app.ActivityManager.RunningTaskInfo; import android.app.IActivityManager.WaitResult; import android.app.ResultInfo; import android.content.ComponentName; import android.content.Context; import android.content.IIntentSender; Loading @@ -43,12 +47,15 @@ import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.SystemClock; import android.util.EventLog; import android.util.Slog; import com.android.internal.app.HeavyWeightSwitcherActivity; import com.android.server.am.ActivityStack.ActivityState; import java.io.FileDescriptor; import java.io.IOException; Loading @@ -57,6 +64,11 @@ import java.util.ArrayList; import java.util.List; public class ActivityStackSupervisor { static final boolean DEBUG_ADD_REMOVE = false; static final boolean DEBUG_APP = false; static final boolean DEBUG_SAVED_STATE = false; static final boolean DEBUG_STATES = false; public static final int HOME_STACK_ID = 0; final ActivityManagerService mService; Loading @@ -73,6 +85,9 @@ public class ActivityStackSupervisor { * new task is created. */ private int mCurTaskId = 0; /** The current user */ private int mCurrentUser; /** The stack containing the launcher app */ private ActivityStack mHomeStack; Loading @@ -89,8 +104,8 @@ public class ActivityStackSupervisor { mLooper = looper; } void init() { mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID, this); void init(int userId) { mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID, this, userId); setMainStack(mHomeStack); mStacks.add(mHomeStack); } Loading Loading @@ -156,7 +171,7 @@ public class ActivityStackSupervisor { if (headless) { Slog.e(TAG, "Starting activities not supported on headless device: " + hr); } else if (stack.realStartActivityLocked(hr, app, true, true)) { } else if (realStartActivityLocked(hr, app, true, true)) { didSomething = true; } } catch (Exception e) { Loading Loading @@ -488,6 +503,174 @@ public class ActivityStackSupervisor { return ActivityManager.START_SUCCESS; } final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException { r.startFreezingScreenLocked(app, 0); mService.mWindowManager.setAppVisibility(r.appToken, true); // 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 = mService.mWindowManager.updateOrientationFromAppTokens( mService.mConfiguration, r.mayFreezeScreenLocked(app) ? r.appToken : null); mService.updateConfigurationLocked(config, r, false, false); } r.app = app; app.waitingToKill = null; r.launchCount++; r.lastLaunchTime = SystemClock.uptimeMillis(); if (localLOGV) Slog.v(TAG, "Launching: " + r); int idx = app.activities.indexOf(r); if (idx < 0) { app.activities.add(r); } mService.updateLruProcessLocked(app, true); 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); } if (r.isHomeActivity) { mService.mHomeProcess = app; } mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName()); 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.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken, System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration), r.compat, 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; } // This is the first time we failed -- restart process and // retry. app.activities.remove(r); throw e; } r.launchFailed = false; if (stack.updateLRUListLocked(r)) { 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); } 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 (isMainStack(stack)) { mService.startSetupActivityLocked(); } return true; } void handleAppDiedLocked(ProcessRecord app, boolean restarting) { // Just in case. final int numStacks = mStacks.size(); Loading Loading @@ -599,7 +782,8 @@ public class ActivityStackSupervisor { break; } } mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId, this)); mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId, this, mCurrentUser)); return mLastStackId; } } Loading Loading @@ -694,6 +878,7 @@ public class ActivityStackSupervisor { } boolean switchUserLocked(int userId, UserStartedState uss) { mCurrentUser = userId; boolean haveActivities = false; final int numStacks = mStacks.size(); for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { Loading Loading
services/java/com/android/server/am/ActivityManagerService.java +19 −9 Original line number Diff line number Diff line Loading @@ -1466,7 +1466,7 @@ public final class ActivityManagerService extends ActivityManagerNative m.mFactoryTest = factoryTest; m.mStackSupervisor = new ActivityStackSupervisor(m, context, thr.mLooper); m.mStackSupervisor.init(); m.mStackSupervisor.init(m.mCurrentUserId); m.mBatteryStatsService.publish(context); m.mUsageStatsService.publish(context); Loading Loading @@ -1886,6 +1886,13 @@ public final class ActivityManagerService extends ActivityManagerNative mHandler.obtainMessage(IMMERSIVE_MODE_LOCK_MSG, (nextState) ? 1 : 0, 0, r)); } final void showAskCompatModeDialogLocked(ActivityRecord r) { Message msg = Message.obtain(); msg.what = SHOW_COMPAT_MODE_DIALOG_MSG; msg.obj = r.task.askedCompatMode ? null : r; mHandler.sendMessage(msg); } private final void updateLruProcessInternalLocked(ProcessRecord app, int bestPos) { // put it on the LRU to keep track of when it should be exited. int lrui = mLruProcesses.indexOf(app); Loading Loading @@ -3491,6 +3498,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } @Override public boolean clearApplicationUserData(final String packageName, final IPackageDataObserver observer, int userId) { enforceNotIsolatedCaller("clearApplicationUserData"); Loading Loading @@ -3546,6 +3554,7 @@ public final class ActivityManagerService extends ActivityManagerNative return true; } @Override public void killBackgroundProcesses(final String packageName, int userId) { if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES) != PackageManager.PERMISSION_GRANTED && Loading Loading @@ -3582,6 +3591,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } @Override public void killAllBackgroundProcesses() { if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES) != PackageManager.PERMISSION_GRANTED) { Loading
services/java/com/android/server/am/ActivityStack.java +23 −197 Original line number Diff line number Diff line Loading @@ -42,7 +42,6 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.content.res.Resources; Loading @@ -54,18 +53,15 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.PowerManager; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.util.EventLog; import android.util.Log; import android.util.Slog; import android.view.Display; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.util.ArrayList; Loading @@ -88,10 +84,10 @@ final class ActivityStack { static final boolean DEBUG_TASKS = ActivityManagerService.DEBUG_TASKS; static final boolean DEBUG_CLEANUP = ActivityManagerService.DEBUG_CLEANUP; static final boolean DEBUG_STATES = false; static final boolean DEBUG_ADD_REMOVE = false; static final boolean DEBUG_SAVED_STATE = false; static final boolean DEBUG_APP = false; static final boolean DEBUG_STATES = ActivityStackSupervisor.DEBUG_STATES; static final boolean DEBUG_ADD_REMOVE = ActivityStackSupervisor.DEBUG_ADD_REMOVE; static final boolean DEBUG_SAVED_STATE = ActivityStackSupervisor.DEBUG_SAVED_STATE; static final boolean DEBUG_APP = ActivityStackSupervisor.DEBUG_APP; static final boolean VALIDATE_TOKENS = ActivityManagerService.VALIDATE_TOKENS; Loading Loading @@ -445,7 +441,7 @@ final class ActivityStack { } ActivityStack(ActivityManagerService service, Context context, Looper looper, int stackId, ActivityStackSupervisor supervisor) { ActivityStackSupervisor supervisor, int userId) { mHandler = new ActivityStackHandler(looper); mService = service; mContext = context; Loading @@ -456,6 +452,7 @@ final class ActivityStack { mLaunchingActivity.setReferenceCounted(false); mStackId = stackId; mStackSupervisor = supervisor; mCurrentUser = userId; } private boolean okToShow(ActivityRecord r) { Loading Loading @@ -541,7 +538,7 @@ final class ActivityStack { return null; } private final boolean updateLRUListLocked(ActivityRecord r) { final boolean updateLRUListLocked(ActivityRecord r) { final boolean hadit = mLRUActivities.remove(r); mLRUActivities.add(r); return hadit; Loading Loading @@ -619,13 +616,6 @@ final class ActivityStack { return null; } final void showAskCompatModeDialogLocked(ActivityRecord r) { Message msg = Message.obtain(); msg.what = ActivityManagerService.SHOW_COMPAT_MODE_DIALOG_MSG; msg.obj = r.task.askedCompatMode ? null : r; mService.mHandler.sendMessage(msg); } /* * Move the activities around in the stack to bring a user to the foreground. * @return whether there are any activities for the specified user. Loading Loading @@ -660,150 +650,7 @@ final class ActivityStack { return haveActivities; } final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException { r.startFreezingScreenLocked(app, 0); mService.mWindowManager.setAppVisibility(r.appToken, true); // 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 = mService.mWindowManager.updateOrientationFromAppTokens( mService.mConfiguration, r.mayFreezeScreenLocked(app) ? r.appToken : null); mService.updateConfigurationLocked(config, r, false, false); } r.app = app; app.waitingToKill = null; r.launchCount++; r.lastLaunchTime = SystemClock.uptimeMillis(); if (localLOGV) Slog.v(TAG, "Launching: " + r); int idx = app.activities.indexOf(r); if (idx < 0) { app.activities.add(r); } mService.updateLruProcessLocked(app, true); 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); } if (r.isHomeActivity) { mService.mHomeProcess = app; } mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName()); r.sleeping = false; r.forceNewConfig = false; 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.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken, System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration), r.compat, 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) { Log.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); requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null, "2nd-crash", false); return false; } // This is the first time we failed -- restart process and // retry. app.activities.remove(r); throw e; } r.launchFailed = false; if (updateLRUListLocked(r)) { 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. void minimalResumeActivityLocked(ActivityRecord r) { r.state = ActivityState.RESUMED; if (DEBUG_STATES) Slog.v(TAG, "Moving to RESUMED: " + r + " (starting new instance)"); Loading @@ -814,26 +661,6 @@ final class ActivityStack { completeResumeLocked(r); checkReadyForSleepLocked(); if (DEBUG_SAVED_STATE) Slog.i(TAG, "Launch completed; removing icicle of " + r.icicle); } 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 (mStackSupervisor.isMainStack(this)) { mService.startSetupActivityLocked(); } return true; } private final void startSpecificActivityLocked(ActivityRecord r, Loading @@ -854,7 +681,7 @@ final class ActivityStack { if (app != null && app.thread != null) { try { app.addPackage(r.info.packageName); realStartActivityLocked(r, app, andResume, checkConfig); mStackSupervisor.realStartActivityLocked(r, app, andResume, checkConfig); return; } catch (RemoteException e) { Slog.w(TAG, "Exception when starting activity " Loading Loading @@ -1749,7 +1576,7 @@ final class ActivityStack { next.task.taskId, next.shortComponentName); next.sleeping = false; showAskCompatModeDialogLocked(next); mService.showAskCompatModeDialogLocked(next); next.app.pendingUiClean = true; next.app.thread.scheduleResumeActivity(next.appToken, mService.isNextTransitionForward()); Loading Loading @@ -3429,7 +3256,6 @@ final class ActivityStack { private static final int FINISH_AFTER_PAUSE = 1; private static final int FINISH_AFTER_VISIBLE = 2; private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj) { // First things first: if this activity is currently visible, Loading
services/java/com/android/server/am/ActivityStackSupervisor.java +189 −4 Original line number Diff line number Diff line Loading @@ -16,11 +16,14 @@ package com.android.server.am; import static com.android.server.am.ActivityManagerService.localLOGV; import static com.android.server.am.ActivityManagerService.DEBUG_CLEANUP; import static com.android.server.am.ActivityManagerService.DEBUG_CONFIGURATION; import static com.android.server.am.ActivityManagerService.DEBUG_PAUSE; import static com.android.server.am.ActivityManagerService.DEBUG_SWITCH; import static com.android.server.am.ActivityManagerService.TAG; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.AppGlobals; Loading @@ -29,6 +32,7 @@ import android.app.IThumbnailReceiver; import android.app.PendingIntent; import android.app.ActivityManager.RunningTaskInfo; import android.app.IActivityManager.WaitResult; import android.app.ResultInfo; import android.content.ComponentName; import android.content.Context; import android.content.IIntentSender; Loading @@ -43,12 +47,15 @@ import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.SystemClock; import android.util.EventLog; import android.util.Slog; import com.android.internal.app.HeavyWeightSwitcherActivity; import com.android.server.am.ActivityStack.ActivityState; import java.io.FileDescriptor; import java.io.IOException; Loading @@ -57,6 +64,11 @@ import java.util.ArrayList; import java.util.List; public class ActivityStackSupervisor { static final boolean DEBUG_ADD_REMOVE = false; static final boolean DEBUG_APP = false; static final boolean DEBUG_SAVED_STATE = false; static final boolean DEBUG_STATES = false; public static final int HOME_STACK_ID = 0; final ActivityManagerService mService; Loading @@ -73,6 +85,9 @@ public class ActivityStackSupervisor { * new task is created. */ private int mCurTaskId = 0; /** The current user */ private int mCurrentUser; /** The stack containing the launcher app */ private ActivityStack mHomeStack; Loading @@ -89,8 +104,8 @@ public class ActivityStackSupervisor { mLooper = looper; } void init() { mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID, this); void init(int userId) { mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID, this, userId); setMainStack(mHomeStack); mStacks.add(mHomeStack); } Loading Loading @@ -156,7 +171,7 @@ public class ActivityStackSupervisor { if (headless) { Slog.e(TAG, "Starting activities not supported on headless device: " + hr); } else if (stack.realStartActivityLocked(hr, app, true, true)) { } else if (realStartActivityLocked(hr, app, true, true)) { didSomething = true; } } catch (Exception e) { Loading Loading @@ -488,6 +503,174 @@ public class ActivityStackSupervisor { return ActivityManager.START_SUCCESS; } final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException { r.startFreezingScreenLocked(app, 0); mService.mWindowManager.setAppVisibility(r.appToken, true); // 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 = mService.mWindowManager.updateOrientationFromAppTokens( mService.mConfiguration, r.mayFreezeScreenLocked(app) ? r.appToken : null); mService.updateConfigurationLocked(config, r, false, false); } r.app = app; app.waitingToKill = null; r.launchCount++; r.lastLaunchTime = SystemClock.uptimeMillis(); if (localLOGV) Slog.v(TAG, "Launching: " + r); int idx = app.activities.indexOf(r); if (idx < 0) { app.activities.add(r); } mService.updateLruProcessLocked(app, true); 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); } if (r.isHomeActivity) { mService.mHomeProcess = app; } mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName()); 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.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken, System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration), r.compat, 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; } // This is the first time we failed -- restart process and // retry. app.activities.remove(r); throw e; } r.launchFailed = false; if (stack.updateLRUListLocked(r)) { 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); } 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 (isMainStack(stack)) { mService.startSetupActivityLocked(); } return true; } void handleAppDiedLocked(ProcessRecord app, boolean restarting) { // Just in case. final int numStacks = mStacks.size(); Loading Loading @@ -599,7 +782,8 @@ public class ActivityStackSupervisor { break; } } mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId, this)); mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId, this, mCurrentUser)); return mLastStackId; } } Loading Loading @@ -694,6 +878,7 @@ public class ActivityStackSupervisor { } boolean switchUserLocked(int userId, UserStartedState uss) { mCurrentUser = userId; boolean haveActivities = false; final int numStacks = mStacks.size(); for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { Loading