* commit '5503d803ecee63d417128d3849717b59b971fc08': Fix issue #3377999: Activities need to be stopped when sleeping
This commit is contained in:
@@ -4390,6 +4390,7 @@ public class Activity extends ContextThemeWrapper
|
||||
mFragments.dispatchPause();
|
||||
mCalled = false;
|
||||
onPause();
|
||||
mResumed = false;
|
||||
if (!mCalled && getApplicationInfo().targetSdkVersion
|
||||
>= android.os.Build.VERSION_CODES.GINGERBREAD) {
|
||||
throw new SuperNotCalledException(
|
||||
|
||||
@@ -376,6 +376,14 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
|
||||
return true;
|
||||
}
|
||||
|
||||
case ACTIVITY_SLEPT_TRANSACTION: {
|
||||
data.enforceInterface(IActivityManager.descriptor);
|
||||
IBinder token = data.readStrongBinder();
|
||||
activitySlept(token);
|
||||
reply.writeNoException();
|
||||
return true;
|
||||
}
|
||||
|
||||
case ACTIVITY_DESTROYED_TRANSACTION: {
|
||||
data.enforceInterface(IActivityManager.descriptor);
|
||||
IBinder token = data.readStrongBinder();
|
||||
@@ -1719,6 +1727,17 @@ class ActivityManagerProxy implements IActivityManager
|
||||
data.recycle();
|
||||
reply.recycle();
|
||||
}
|
||||
public void activitySlept(IBinder token) throws RemoteException
|
||||
{
|
||||
Parcel data = Parcel.obtain();
|
||||
Parcel reply = Parcel.obtain();
|
||||
data.writeInterfaceToken(IActivityManager.descriptor);
|
||||
data.writeStrongBinder(token);
|
||||
mRemote.transact(ACTIVITY_SLEPT_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
|
||||
reply.readException();
|
||||
data.recycle();
|
||||
reply.recycle();
|
||||
}
|
||||
public void activityDestroyed(IBinder token) throws RemoteException
|
||||
{
|
||||
Parcel data = Parcel.obtain();
|
||||
|
||||
@@ -424,6 +424,10 @@ public final class ActivityThread {
|
||||
token);
|
||||
}
|
||||
|
||||
public final void scheduleSleeping(IBinder token, boolean sleeping) {
|
||||
queueOrSendMessage(H.SLEEPING, token, sleeping ? 1 : 0);
|
||||
}
|
||||
|
||||
public final void scheduleResumeActivity(IBinder token, boolean isForward) {
|
||||
queueOrSendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0);
|
||||
}
|
||||
@@ -932,6 +936,7 @@ public final class ActivityThread {
|
||||
public static final int SCHEDULE_CRASH = 134;
|
||||
public static final int DUMP_HEAP = 135;
|
||||
public static final int DUMP_ACTIVITY = 136;
|
||||
public static final int SLEEPING = 137;
|
||||
String codeToString(int code) {
|
||||
if (DEBUG_MESSAGES) {
|
||||
switch (code) {
|
||||
@@ -972,6 +977,7 @@ public final class ActivityThread {
|
||||
case SCHEDULE_CRASH: return "SCHEDULE_CRASH";
|
||||
case DUMP_HEAP: return "DUMP_HEAP";
|
||||
case DUMP_ACTIVITY: return "DUMP_ACTIVITY";
|
||||
case SLEEPING: return "SLEEPING";
|
||||
}
|
||||
}
|
||||
return "(unknown)";
|
||||
@@ -1104,6 +1110,9 @@ public final class ActivityThread {
|
||||
case DUMP_ACTIVITY:
|
||||
handleDumpActivity((DumpComponentInfo)msg.obj);
|
||||
break;
|
||||
case SLEEPING:
|
||||
handleSleeping((IBinder)msg.obj, msg.arg1 != 0);
|
||||
break;
|
||||
}
|
||||
if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + msg.what);
|
||||
}
|
||||
@@ -2651,6 +2660,42 @@ public final class ActivityThread {
|
||||
}
|
||||
}
|
||||
|
||||
private final void handleSleeping(IBinder token, boolean sleeping) {
|
||||
ActivityClientRecord r = mActivities.get(token);
|
||||
|
||||
if (r == null) {
|
||||
Log.w(TAG, "handleWindowVisibility: no activity for token " + token);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sleeping) {
|
||||
if (!r.stopped) {
|
||||
try {
|
||||
// Now we are idle.
|
||||
r.activity.performStop();
|
||||
} catch (Exception e) {
|
||||
if (!mInstrumentation.onException(r.activity, e)) {
|
||||
throw new RuntimeException(
|
||||
"Unable to stop activity "
|
||||
+ r.intent.getComponent().toShortString()
|
||||
+ ": " + e.toString(), e);
|
||||
}
|
||||
}
|
||||
r.stopped = true;
|
||||
}
|
||||
// Tell activity manager we slept.
|
||||
try {
|
||||
ActivityManagerNative.getDefault().activitySlept(r.token);
|
||||
} catch (RemoteException ex) {
|
||||
}
|
||||
} else {
|
||||
if (r.stopped && r.activity.mVisibleFromServer) {
|
||||
r.activity.performRestart();
|
||||
r.stopped = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final void deliverResults(ActivityClientRecord r, List<ResultInfo> results) {
|
||||
final int N = results.size();
|
||||
for (int i=0; i<N; i++) {
|
||||
|
||||
@@ -97,6 +97,15 @@ public abstract class ApplicationThreadNative extends Binder
|
||||
return true;
|
||||
}
|
||||
|
||||
case SCHEDULE_SLEEPING_TRANSACTION:
|
||||
{
|
||||
data.enforceInterface(IApplicationThread.descriptor);
|
||||
IBinder b = data.readStrongBinder();
|
||||
boolean sleeping = data.readInt() != 0;
|
||||
scheduleSleeping(b, sleeping);
|
||||
return true;
|
||||
}
|
||||
|
||||
case SCHEDULE_RESUME_ACTIVITY_TRANSACTION:
|
||||
{
|
||||
data.enforceInterface(IApplicationThread.descriptor);
|
||||
@@ -503,6 +512,17 @@ class ApplicationThreadProxy implements IApplicationThread {
|
||||
data.recycle();
|
||||
}
|
||||
|
||||
public final void scheduleSleeping(IBinder token,
|
||||
boolean sleeping) throws RemoteException {
|
||||
Parcel data = Parcel.obtain();
|
||||
data.writeInterfaceToken(IApplicationThread.descriptor);
|
||||
data.writeStrongBinder(token);
|
||||
data.writeInt(sleeping ? 1 : 0);
|
||||
mRemote.transact(SCHEDULE_SLEEPING_TRANSACTION, data, null,
|
||||
IBinder.FLAG_ONEWAY);
|
||||
data.recycle();
|
||||
}
|
||||
|
||||
public final void scheduleResumeActivity(IBinder token, boolean isForward)
|
||||
throws RemoteException {
|
||||
Parcel data = Parcel.obtain();
|
||||
|
||||
@@ -124,6 +124,8 @@ public interface IActivityManager extends IInterface {
|
||||
public void activityStopped(IBinder token, Bundle state,
|
||||
Bitmap thumbnail, CharSequence description) throws RemoteException;
|
||||
/* oneway */
|
||||
public void activitySlept(IBinder token) throws RemoteException;
|
||||
/* oneway */
|
||||
public void activityDestroyed(IBinder token) throws RemoteException;
|
||||
public String getCallingPackage(IBinder token) throws RemoteException;
|
||||
public ComponentName getCallingActivity(IBinder token) throws RemoteException;
|
||||
@@ -553,4 +555,5 @@ public interface IActivityManager extends IInterface {
|
||||
int DUMP_HEAP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+119;
|
||||
int START_ACTIVITIES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+120;
|
||||
int START_ACTIVITIES_IN_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+121;
|
||||
int ACTIVITY_SLEPT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+122;
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ public interface IApplicationThread extends IInterface {
|
||||
void scheduleStopActivity(IBinder token, boolean showWindow,
|
||||
int configChanges) throws RemoteException;
|
||||
void scheduleWindowVisibility(IBinder token, boolean showWindow) throws RemoteException;
|
||||
void scheduleSleeping(IBinder token, boolean sleeping) throws RemoteException;
|
||||
void scheduleResumeActivity(IBinder token, boolean isForward) throws RemoteException;
|
||||
void scheduleSendResult(IBinder token, List<ResultInfo> results) throws RemoteException;
|
||||
void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
|
||||
@@ -137,7 +138,7 @@ public interface IApplicationThread extends IInterface {
|
||||
int SCHEDULE_LOW_MEMORY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+23;
|
||||
int SCHEDULE_ACTIVITY_CONFIGURATION_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+24;
|
||||
int SCHEDULE_RELAUNCH_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+25;
|
||||
|
||||
int SCHEDULE_SLEEPING_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+26;
|
||||
int PROFILER_CONTROL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+27;
|
||||
int SET_SCHEDULING_GROUP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+28;
|
||||
int SCHEDULE_CREATE_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+29;
|
||||
|
||||
@@ -5858,16 +5858,18 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
return pfd;
|
||||
}
|
||||
|
||||
// Actually is sleeping or shutting down or whatever else in the future
|
||||
// is an inactive state.
|
||||
public boolean isSleeping() {
|
||||
return mSleeping || mShuttingDown;
|
||||
}
|
||||
|
||||
public void goingToSleep() {
|
||||
synchronized(this) {
|
||||
mSleeping = true;
|
||||
mWindowManager.setEventDispatching(false);
|
||||
|
||||
if (mMainStack.mResumedActivity != null) {
|
||||
mMainStack.pauseIfSleepingLocked();
|
||||
} else {
|
||||
Slog.w(TAG, "goingToSleep with no resumed activity!");
|
||||
}
|
||||
mMainStack.stopIfSleepingLocked();
|
||||
|
||||
// Initialize the wake times of all processes.
|
||||
checkExcessivePowerUsageLocked(false);
|
||||
@@ -5891,7 +5893,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
mWindowManager.setEventDispatching(false);
|
||||
|
||||
if (mMainStack.mResumedActivity != null) {
|
||||
mMainStack.pauseIfSleepingLocked();
|
||||
mMainStack.stopIfSleepingLocked();
|
||||
final long endTime = System.currentTimeMillis() + timeout;
|
||||
while (mMainStack.mResumedActivity != null
|
||||
|| mMainStack.mPausingActivity != null) {
|
||||
@@ -5915,13 +5917,30 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
return timedout;
|
||||
}
|
||||
|
||||
public final void activitySlept(IBinder token) {
|
||||
if (localLOGV) Slog.v(
|
||||
TAG, "Activity slept: token=" + token);
|
||||
|
||||
ActivityRecord r = null;
|
||||
|
||||
final long origId = Binder.clearCallingIdentity();
|
||||
|
||||
synchronized (this) {
|
||||
int index = mMainStack.indexOfTokenLocked(token);
|
||||
if (index >= 0) {
|
||||
r = (ActivityRecord)mMainStack.mHistory.get(index);
|
||||
mMainStack.activitySleptLocked(r);
|
||||
}
|
||||
}
|
||||
|
||||
Binder.restoreCallingIdentity(origId);
|
||||
}
|
||||
|
||||
public void wakingUp() {
|
||||
synchronized(this) {
|
||||
if (mMainStack.mGoingToSleep.isHeld()) {
|
||||
mMainStack.mGoingToSleep.release();
|
||||
}
|
||||
mWindowManager.setEventDispatching(true);
|
||||
mSleeping = false;
|
||||
mMainStack.awakeFromSleepingLocked();
|
||||
mMainStack.resumeTopActivityLocked(null);
|
||||
}
|
||||
}
|
||||
@@ -7520,6 +7539,11 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
pw.println(" Activities waiting to stop:");
|
||||
dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
|
||||
}
|
||||
if (mMainStack.mGoingToSleepActivities.size() > 0) {
|
||||
pw.println(" ");
|
||||
pw.println(" Activities waiting to sleep:");
|
||||
dumpHistoryList(pw, mMainStack.mGoingToSleepActivities, " ", "Sleep", false);
|
||||
}
|
||||
if (mMainStack.mFinishingActivities.size() > 0) {
|
||||
pw.println(" ");
|
||||
pw.println(" Activities waiting to finish:");
|
||||
@@ -7531,6 +7555,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
|
||||
pw.println(" mFocusedActivity: " + mFocusedActivity);
|
||||
pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
|
||||
pw.println(" mSleepTimeout: " + mMainStack.mSleepTimeout);
|
||||
|
||||
if (dumpAll && mRecentTasks.size() > 0) {
|
||||
pw.println(" ");
|
||||
|
||||
@@ -102,6 +102,7 @@ class ActivityRecord extends IApplicationToken.Stub {
|
||||
boolean inHistory; // are we in the history stack?
|
||||
int launchMode; // the launch mode activity attribute.
|
||||
boolean visible; // does this activity's window need to be shown?
|
||||
boolean sleeping; // have we told the activity to sleep?
|
||||
boolean waitingVisible; // true if waiting for a new act to become vis
|
||||
boolean nowVisible; // is this activity's window visible?
|
||||
boolean thumbnailNeeded;// has someone requested a thumbnail?
|
||||
@@ -168,9 +169,10 @@ class ActivityRecord extends IApplicationToken.Stub {
|
||||
pw.print(" launchMode="); pw.println(launchMode);
|
||||
pw.print(prefix); pw.print("fullscreen="); pw.print(fullscreen);
|
||||
pw.print(" visible="); pw.print(visible);
|
||||
pw.print(" frozenBeforeDestroy="); pw.print(frozenBeforeDestroy);
|
||||
pw.print(" thumbnailNeeded="); pw.print(thumbnailNeeded);
|
||||
pw.print(" sleeping="); pw.print(sleeping);
|
||||
pw.print(" idle="); pw.println(idle);
|
||||
pw.print(prefix); pw.print("frozenBeforeDestroy="); pw.print(frozenBeforeDestroy);
|
||||
pw.print(" thumbnailNeeded="); pw.println(thumbnailNeeded);
|
||||
if (launchTime != 0 || startTime != 0) {
|
||||
pw.print(prefix); pw.print("launchTime=");
|
||||
TimeUtils.formatDuration(launchTime, pw); pw.print(" startTime=");
|
||||
@@ -597,7 +599,25 @@ class ActivityRecord extends IApplicationToken.Stub {
|
||||
public boolean isInterestingToUserLocked() {
|
||||
return visible || nowVisible || state == ActivityState.PAUSING ||
|
||||
state == ActivityState.RESUMED;
|
||||
}
|
||||
}
|
||||
|
||||
public void setSleeping(boolean _sleeping) {
|
||||
if (sleeping == _sleeping) {
|
||||
return;
|
||||
}
|
||||
if (app != null && app.thread != null) {
|
||||
try {
|
||||
app.thread.scheduleSleeping(this, _sleeping);
|
||||
if (sleeping && !stack.mGoingToSleepActivities.contains(this)) {
|
||||
stack.mGoingToSleepActivities.add(this);
|
||||
}
|
||||
sleeping = _sleeping;
|
||||
} catch (RemoteException e) {
|
||||
Slog.w(ActivityStack.TAG, "Exception thrown when sleeping: "
|
||||
+ intent.getComponent(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
if (stringName != null) {
|
||||
|
||||
@@ -92,6 +92,9 @@ public class ActivityStack {
|
||||
// next activity.
|
||||
static final int PAUSE_TIMEOUT = 500;
|
||||
|
||||
// How long we can hold the sleep wake lock before giving up.
|
||||
static final int SLEEP_TIMEOUT = 5*1000;
|
||||
|
||||
// How long we can hold the launch wake lock before giving up.
|
||||
static final int LAUNCH_TIMEOUT = 10*1000;
|
||||
|
||||
@@ -157,6 +160,12 @@ public class ActivityStack {
|
||||
final ArrayList<ActivityRecord> mStoppingActivities
|
||||
= new ArrayList<ActivityRecord>();
|
||||
|
||||
/**
|
||||
* List of activities that are in the process of going to sleep.
|
||||
*/
|
||||
final ArrayList<ActivityRecord> mGoingToSleepActivities
|
||||
= new ArrayList<ActivityRecord>();
|
||||
|
||||
/**
|
||||
* Animations that for the current transition have requested not to
|
||||
* be considered for the transition animation.
|
||||
@@ -238,9 +247,15 @@ public class ActivityStack {
|
||||
|
||||
long mInitialStartTime = 0;
|
||||
|
||||
/**
|
||||
* Set when we have taken too long waiting to go to sleep.
|
||||
*/
|
||||
boolean mSleepTimeout = false;
|
||||
|
||||
int mThumbnailWidth = -1;
|
||||
int mThumbnailHeight = -1;
|
||||
|
||||
static final int SLEEP_TIMEOUT_MSG = 8;
|
||||
static final int PAUSE_TIMEOUT_MSG = 9;
|
||||
static final int IDLE_TIMEOUT_MSG = 10;
|
||||
static final int IDLE_NOW_MSG = 11;
|
||||
@@ -255,6 +270,13 @@ public class ActivityStack {
|
||||
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case SLEEP_TIMEOUT_MSG: {
|
||||
if (mService.isSleeping()) {
|
||||
Slog.w(TAG, "Sleep timeout! Sleeping now.");
|
||||
mSleepTimeout = true;
|
||||
checkReadyForSleepLocked();
|
||||
}
|
||||
} break;
|
||||
case PAUSE_TIMEOUT_MSG: {
|
||||
IBinder token = (IBinder)msg.obj;
|
||||
// We don't at this point know if the activity is fullscreen,
|
||||
@@ -514,6 +536,7 @@ public class ActivityStack {
|
||||
mService.mHomeProcess = app;
|
||||
}
|
||||
mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
|
||||
r.sleeping = false;
|
||||
app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
|
||||
System.identityHashCode(r),
|
||||
r.info, r.icicle, results, newIntents, !andResume,
|
||||
@@ -575,7 +598,7 @@ public class ActivityStack {
|
||||
mService.addRecentTaskLocked(r.task);
|
||||
}
|
||||
completeResumeLocked(r);
|
||||
pauseIfSleepingLocked();
|
||||
checkReadyForSleepLocked();
|
||||
} else {
|
||||
// This activity is not starting in the resumed state... which
|
||||
// should look like we asked it to pause+stop (but remain visible),
|
||||
@@ -631,8 +654,8 @@ public class ActivityStack {
|
||||
"activity", r.intent.getComponent(), false);
|
||||
}
|
||||
|
||||
void pauseIfSleepingLocked() {
|
||||
if (mService.mSleeping || mService.mShuttingDown) {
|
||||
void stopIfSleepingLocked() {
|
||||
if (mService.isSleeping()) {
|
||||
if (!mGoingToSleep.isHeld()) {
|
||||
mGoingToSleep.acquire();
|
||||
if (mLaunchingActivity.isHeld()) {
|
||||
@@ -640,16 +663,90 @@ public class ActivityStack {
|
||||
mService.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
|
||||
}
|
||||
}
|
||||
mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
|
||||
Message msg = mHandler.obtainMessage(SLEEP_TIMEOUT_MSG);
|
||||
mHandler.sendMessageDelayed(msg, SLEEP_TIMEOUT);
|
||||
checkReadyForSleepLocked();
|
||||
}
|
||||
}
|
||||
|
||||
// If we are not currently pausing an activity, get the current
|
||||
// one to pause. If we are pausing one, we will just let that stuff
|
||||
// run and release the wake lock when all done.
|
||||
if (mPausingActivity == null) {
|
||||
if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause...");
|
||||
void awakeFromSleepingLocked() {
|
||||
mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
|
||||
mSleepTimeout = false;
|
||||
if (mGoingToSleep.isHeld()) {
|
||||
mGoingToSleep.release();
|
||||
}
|
||||
// Ensure activities are no longer sleeping.
|
||||
for (int i=mHistory.size()-1; i>=0; i--) {
|
||||
ActivityRecord r = (ActivityRecord)mHistory.get(i);
|
||||
r.setSleeping(false);
|
||||
}
|
||||
mGoingToSleepActivities.clear();
|
||||
}
|
||||
|
||||
void activitySleptLocked(ActivityRecord r) {
|
||||
mGoingToSleepActivities.remove(r);
|
||||
checkReadyForSleepLocked();
|
||||
}
|
||||
|
||||
void checkReadyForSleepLocked() {
|
||||
if (!mService.isSleeping()) {
|
||||
// Do not care.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mSleepTimeout) {
|
||||
if (mResumedActivity != null) {
|
||||
// Still have something resumed; can't sleep until it is paused.
|
||||
if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause " + mResumedActivity);
|
||||
if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
|
||||
startPausingLocked(false, true);
|
||||
return;
|
||||
}
|
||||
if (mPausingActivity != null) {
|
||||
// Still waiting for something to pause; can't sleep yet.
|
||||
if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still waiting to pause " + mPausingActivity);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mStoppingActivities.size() > 0) {
|
||||
// Still need to tell some activities to stop; can't sleep yet.
|
||||
if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to stop "
|
||||
+ mStoppingActivities.size() + " activities");
|
||||
Message msg = Message.obtain();
|
||||
msg.what = IDLE_NOW_MSG;
|
||||
mHandler.sendMessage(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
ensureActivitiesVisibleLocked(null, 0);
|
||||
|
||||
// Make sure any stopped but visible activities are now sleeping.
|
||||
// This ensures that the activity's onStop() is called.
|
||||
for (int i=mHistory.size()-1; i>=0; i--) {
|
||||
ActivityRecord r = (ActivityRecord)mHistory.get(i);
|
||||
if (r.state == ActivityState.STOPPING || r.state == ActivityState.STOPPED) {
|
||||
r.setSleeping(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (mGoingToSleepActivities.size() > 0) {
|
||||
// Still need to tell some activities to sleep; can't sleep yet.
|
||||
if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to sleep "
|
||||
+ mGoingToSleepActivities.size() + " activities");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
|
||||
|
||||
if (mGoingToSleep.isHeld()) {
|
||||
mGoingToSleep.release();
|
||||
}
|
||||
if (mService.mShuttingDown) {
|
||||
mService.notifyAll();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final Bitmap screenshotActivities(ActivityRecord who) {
|
||||
@@ -813,6 +910,8 @@ public class ActivityStack {
|
||||
Message msg = Message.obtain();
|
||||
msg.what = IDLE_NOW_MSG;
|
||||
mHandler.sendMessage(msg);
|
||||
} else {
|
||||
checkReadyForSleepLocked();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -822,15 +921,10 @@ public class ActivityStack {
|
||||
mPausingActivity = null;
|
||||
}
|
||||
|
||||
if (!mService.mSleeping && !mService.mShuttingDown) {
|
||||
if (!mService.isSleeping()) {
|
||||
resumeTopActivityLocked(prev);
|
||||
} else {
|
||||
if (mGoingToSleep.isHeld()) {
|
||||
mGoingToSleep.release();
|
||||
}
|
||||
if (mService.mShuttingDown) {
|
||||
mService.notifyAll();
|
||||
}
|
||||
checkReadyForSleepLocked();
|
||||
}
|
||||
|
||||
if (prev != null) {
|
||||
@@ -985,6 +1079,7 @@ public class ActivityStack {
|
||||
TAG, "Making visible and scheduling visibility: " + r);
|
||||
try {
|
||||
mService.mWindowManager.setAppVisibility(r, true);
|
||||
r.sleeping = false;
|
||||
r.app.thread.scheduleWindowVisibility(r, true);
|
||||
r.stopFreezingScreenLocked(false);
|
||||
} catch (Exception e) {
|
||||
@@ -1114,6 +1209,8 @@ public class ActivityStack {
|
||||
// The activity may be waiting for stop, but that is no longer
|
||||
// appropriate for it.
|
||||
mStoppingActivities.remove(next);
|
||||
mGoingToSleepActivities.remove(next);
|
||||
next.sleeping = false;
|
||||
mWaitingVisibleActivities.remove(next);
|
||||
|
||||
if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
|
||||
@@ -1315,10 +1412,11 @@ public class ActivityStack {
|
||||
System.identityHashCode(next),
|
||||
next.task.taskId, next.shortComponentName);
|
||||
|
||||
next.sleeping = false;
|
||||
next.app.thread.scheduleResumeActivity(next,
|
||||
mService.isNextTransitionForward());
|
||||
|
||||
pauseIfSleepingLocked();
|
||||
checkReadyForSleepLocked();
|
||||
|
||||
} catch (Exception e) {
|
||||
// Whoops, need to restart this activity!
|
||||
@@ -2831,6 +2929,9 @@ public class ActivityStack {
|
||||
mService.mWindowManager.setAppVisibility(r, false);
|
||||
}
|
||||
r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
|
||||
if (mService.isSleeping()) {
|
||||
r.setSleeping(true);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Maybe just ignore exceptions here... if the process
|
||||
// has crashed, our death notification will clean things
|
||||
@@ -2874,7 +2975,7 @@ public class ActivityStack {
|
||||
mService.mWindowManager.setAppVisibility(s, false);
|
||||
}
|
||||
}
|
||||
if (!s.waitingVisible && remove) {
|
||||
if ((!s.waitingVisible || mService.isSleeping()) && remove) {
|
||||
if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
|
||||
if (stops == null) {
|
||||
stops = new ArrayList<ActivityRecord>();
|
||||
@@ -3198,6 +3299,8 @@ public class ActivityStack {
|
||||
Message msg = Message.obtain();
|
||||
msg.what = IDLE_NOW_MSG;
|
||||
mHandler.sendMessage(msg);
|
||||
} else {
|
||||
checkReadyForSleepLocked();
|
||||
}
|
||||
}
|
||||
r.state = ActivityState.STOPPING;
|
||||
@@ -3207,6 +3310,7 @@ public class ActivityStack {
|
||||
|
||||
// make sure the record is cleaned out of other places.
|
||||
mStoppingActivities.remove(r);
|
||||
mGoingToSleepActivities.remove(r);
|
||||
mWaitingVisibleActivities.remove(r);
|
||||
if (mResumedActivity == r) {
|
||||
mResumedActivity = null;
|
||||
@@ -3434,6 +3538,7 @@ public class ActivityStack {
|
||||
void removeHistoryRecordsForAppLocked(ProcessRecord app) {
|
||||
removeHistoryRecordsForAppLocked(mLRUActivities, app);
|
||||
removeHistoryRecordsForAppLocked(mStoppingActivities, app);
|
||||
removeHistoryRecordsForAppLocked(mGoingToSleepActivities, app);
|
||||
removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
|
||||
removeHistoryRecordsForAppLocked(mFinishingActivities, app);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user