diff options
-rw-r--r-- | api/current.txt | 1 | ||||
-rw-r--r-- | core/java/android/app/Activity.java | 19 | ||||
-rw-r--r-- | core/java/android/app/ActivityManagerNative.java | 22 | ||||
-rw-r--r-- | core/java/android/app/IActivityManager.java | 3 | ||||
-rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 28 | ||||
-rw-r--r-- | services/java/com/android/server/am/ActivityRecord.java | 17 | ||||
-rw-r--r-- | services/java/com/android/server/am/ActivityStack.java | 24 | ||||
-rw-r--r-- | services/java/com/android/server/wm/WindowManagerService.java | 8 |
8 files changed, 111 insertions, 11 deletions
diff --git a/api/current.txt b/api/current.txt index 92aa494..ac3144d 100644 --- a/api/current.txt +++ b/api/current.txt @@ -2697,6 +2697,7 @@ package android.app { method public void addContentView(android.view.View, android.view.ViewGroup.LayoutParams); method public void closeContextMenu(); method public void closeOptionsMenu(); + method public void convertToOpaque(); method public android.app.PendingIntent createPendingResult(int, android.content.Intent, int); method public final deprecated void dismissDialog(int); method public boolean dispatchGenericMotionEvent(android.view.MotionEvent); diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 7f2f744..e87d805 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -4862,6 +4862,25 @@ public class Activity extends ContextThemeWrapper } /** + * Convert a translucent themed Activity {@link android.R.attr#windowIsTranslucent} to a + * fullscreen opaque Activity. + * + * Call this whenever the background of a translucent Activity has changed to become opaque. + * Doing so will allow the previously visible Activity behind this one to be stopped. Stopped + * apps consume no CPU cycles and are eligible for removal when reclaiming memory. + * + * This call has no effect on non-translucent activities or on activities with the + * {@link android.R.attr#windowIsFloating} attribute. + */ + public void convertToOpaque() { + try { + ActivityManagerNative.getDefault().convertToOpaque(mToken); + } catch (RemoteException e) { + // pass + } + } + + /** * Adjust the current immersive mode setting. * * Note that changing this value will have no effect on the activity's diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 1573398..b966d6d 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -1499,6 +1499,14 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } + case CONVERT_TO_OPAQUE_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IBinder token = data.readStrongBinder(); + convertToOpaque(token); + reply.writeNoException(); + return true; + } + case SET_IMMERSIVE_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder token = data.readStrongBinder(); @@ -3823,7 +3831,19 @@ class ActivityManagerProxy implements IActivityManager data.recycle(); reply.recycle(); } - + + public void convertToOpaque(IBinder token) + throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(token); + mRemote.transact(CONVERT_TO_OPAQUE_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } + public void setImmersive(IBinder token, boolean immersive) throws RemoteException { Parcel data = Parcel.obtain(); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index c8791a4..39f4cfa 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -301,6 +301,8 @@ public interface IActivityManager extends IInterface { public void finishHeavyWeightApp() throws RemoteException; + public void convertToOpaque(IBinder token) throws RemoteException; + public void setImmersive(IBinder token, boolean immersive) throws RemoteException; public boolean isImmersive(IBinder token) throws RemoteException; public boolean isTopActivityImmersive() throws RemoteException; @@ -666,4 +668,5 @@ public interface IActivityManager extends IInterface { int GET_STACK_BOXES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+170; int SET_FOCUSED_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+171; int GET_STACK_BOX_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+172; + int CONVERT_TO_OPAQUE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+173; } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index e37eec6..ad6ae43 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -7910,12 +7910,33 @@ public final class ActivityManagerService extends ActivityManagerNative } } + @Override public void unregisterProcessObserver(IProcessObserver observer) { synchronized (this) { mProcessObservers.unregister(observer); } } + @Override + public void convertToOpaque(IBinder token) { + final long origId = Binder.clearCallingIdentity(); + try { + synchronized (this) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + if (r == null) { + return; + } + if (r.convertToOpaque()) { + mWindowManager.setAppFullscreen(token); + mStackSupervisor.ensureActivitiesVisibleLocked(null, 0); + } + } + } finally { + Binder.restoreCallingIdentity(origId); + } + } + + @Override public void setImmersive(IBinder token, boolean immersive) { synchronized(this) { final ActivityRecord r = ActivityRecord.isInStackLocked(token); @@ -7934,6 +7955,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } + @Override public boolean isImmersive(IBinder token) { synchronized (this) { ActivityRecord r = ActivityRecord.isInStackLocked(token); @@ -8006,7 +8028,7 @@ public final class ActivityManagerService extends ActivityManagerNative String reason = (pReason == null) ? "Unknown" : pReason; // XXX Note: don't acquire main activity lock here, because the window // manager calls in with its locks held. - + boolean killed = false; synchronized (mPidsSelfLocked) { int[] types = new int[pids.length]; @@ -8021,7 +8043,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } } - + // If the worst oom_adj is somewhere in the cached proc LRU range, // then constrain it so we will kill all cached procs. if (worstType < ProcessList.CACHED_APP_MAX_ADJ @@ -8188,7 +8210,7 @@ public final class ActivityManagerService extends ActivityManagerNative // no need to synchronize(this) just to read & return the value return mSystemReady; } - + private static File getCalledPreBootReceiversFile() { File dataDir = Environment.getDataDirectory(); File systemDir = new File(dataDir, "system"); diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java index 561dd0f..f730e07 100644 --- a/services/java/com/android/server/am/ActivityRecord.java +++ b/services/java/com/android/server/am/ActivityRecord.java @@ -71,7 +71,7 @@ final class ActivityRecord { final String processName; // process where this component wants to run final String taskAffinity; // as per ActivityInfo.taskAffinity final boolean stateNotNeeded; // As per ActivityInfo.flags - final boolean fullscreen; // covers the full screen? + boolean fullscreen; // covers the full screen? final boolean noDisplay; // activity is not displayed? final boolean componentSpecified; // did caller specifiy an explicit component? @@ -503,6 +503,21 @@ final class ActivityRecord { } } + boolean convertToOpaque() { + if (fullscreen) { + return false; + } + + AttributeCache.Entry ent = AttributeCache.instance().get(packageName, + realTheme, com.android.internal.R.styleable.Window); + if (ent != null && !ent.array.getBoolean( + com.android.internal.R.styleable.Window_windowIsFloating, false)) { + fullscreen = true; + ++task.numFullscreen; + } + return fullscreen; + } + void putInHistory() { if (!inHistory) { inHistory = true; diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index a9ab53d..8e8bb55 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -1088,11 +1088,25 @@ final class ActivityStack { r.visible = false; try { mWindowManager.setAppVisibility(r.appToken, false); - if ((r.state == ActivityState.STOPPING - || r.state == ActivityState.STOPPED) - && r.app != null && r.app.thread != null) { - if (DEBUG_VISBILITY) Slog.v(TAG, "Scheduling invisibility: " + r); - r.app.thread.scheduleWindowVisibility(r.appToken, false); + switch (r.state) { + case STOPPING: + case STOPPED: + if (r.app != null && r.app.thread != null) { + if (DEBUG_VISBILITY) Slog.v( + TAG, "Scheduling invisibility: " + r); + r.app.thread.scheduleWindowVisibility(r.appToken, false); + } + break; + + case INITIALIZING: + case RESUMED: + case PAUSING: + case PAUSED: + stopActivityLocked(r); + break; + + default: + break; } } catch (Exception e) { // Just skip on any failure; we'll make it diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index 0babeea..ee2ef37 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -98,7 +98,6 @@ import android.util.SparseIntArray; import android.util.TypedValue; import android.view.Choreographer; import android.view.Display; -import android.view.DisplayAdjustments; import android.view.DisplayInfo; import android.view.Gravity; import android.view.IApplicationToken; @@ -4118,6 +4117,13 @@ public class WindowManagerService extends IWindowManager.Stub } } + public void setAppFullscreen(IBinder token) { + AppWindowToken atoken = findAppWindowToken(token); + if (atoken != null) { + atoken.appFullscreen = true; + } + } + boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp, boolean visible, int transit, boolean performLayout) { boolean delayed = false; |