Fix issue #3377999: Activities need to be stopped when sleeping
This is a band-aid over the existing kludgy stopping mechanism where the semantics of stop are different in the activity manager than in the clients. This change is intended to be as unobtrusive as possible, only impacting the sleep case. I have a different change that completely reworks how we stop activities to simply this all a lot by unifying the semantics between the server and client. However, it is too late in HC for such an extensive change. Later I'll revert this one and put in the better solution. Change-Id: Id77f2db1ec83469cdd888acb8fbc4679daa7766e
This commit is contained in:
@@ -4392,6 +4392,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();
|
||||
|
||||
@@ -421,6 +421,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);
|
||||
}
|
||||
@@ -929,6 +933,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) {
|
||||
@@ -969,6 +974,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)";
|
||||
@@ -1101,6 +1107,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);
|
||||
}
|
||||
@@ -2615,6 +2624,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;
|
||||
|
||||
Reference in New Issue
Block a user