diff options
8 files changed, 114 insertions, 32 deletions
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 89510d9f2d15..fa64a0f55337 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -224,4 +224,13 @@ public abstract class ActivityManagerInternal { * Called when the trusted state of Keyguard has changed. */ public abstract void notifyKeyguardTrustedChanged(); + + /** + * Sets if the given pid has an overlay UI or not. + * + * @param pid The pid we are setting overlay UI for. + * @param hasOverlayUi True if the process has overlay UI. + * @see android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY + */ + public abstract void setHasOverlayUi(int pid, boolean hasOverlayUi); } diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 5a640faf08d3..e02d405928c7 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -726,7 +726,10 @@ public interface WindowManager extends ViewManager { * <p> * Requires {@link android.Manifest.permission#SYSTEM_ALERT_WINDOW} permission. * <p> - * In mult-iuser systems shows only on the owning user's screen. + * The system will adjust the importance of processes with this window type to reduce the + * chance of the low-memory-killer killing them. + * <p> + * In multi-user systems shows only on the owning user's screen. */ public static final int TYPE_APPLICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 38; diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index 8e597dc40894..2617d45a6a02 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -786,13 +786,13 @@ public interface WindowManagerPolicy { case TYPE_PRIORITY_PHONE: // SIM errors and unlock. Not sure if this really should be in a high layer. return 9; - case TYPE_DREAM: - // used for Dreams (screensavers with TYPE_DREAM windows) - return 10; case TYPE_SYSTEM_ALERT: // like the ANR / app crashed dialogs return canAddInternalSystemWindow ? 11 : 10; case TYPE_APPLICATION_OVERLAY: + return 12; + case TYPE_DREAM: + // used for Dreams (screensavers with TYPE_DREAM windows) return 13; case TYPE_INPUT_METHOD: // on-screen keyboards and other such input method user interfaces go here. diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 69a3a263bbf8..d5075f153106 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -20141,6 +20141,13 @@ public class ActivityManagerService extends IActivityManager.Stub app.adjType = "force-fg"; app.adjSource = app.forcingToForeground; schedGroup = ProcessList.SCHED_GROUP_DEFAULT; + } else if (app.hasOverlayUi) { + // The process is display an overlay UI. + adj = ProcessList.PERCEPTIBLE_APP_ADJ; + procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; + app.cached = false; + app.adjType = "has-overlay-ui"; + schedGroup = ProcessList.SCHED_GROUP_DEFAULT; } } @@ -22860,6 +22867,33 @@ public class ActivityManagerService extends IActivityManager.Stub } } } + + /** + * Sets if the given pid has an overlay UI or not. + * + * @param pid The pid we are setting overlay UI for. + * @param hasOverlayUi True if the process has overlay UI. + * @see android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY + */ + @Override + public void setHasOverlayUi(int pid, boolean hasOverlayUi) { + synchronized (ActivityManagerService.this) { + final ProcessRecord pr; + synchronized (mPidsSelfLocked) { + pr = mPidsSelfLocked.get(pid); + if (pr == null) { + Slog.w(TAG, "setHasOverlayUi called on unknown pid: " + pid); + return; + } + } + if (pr.hasOverlayUi == hasOverlayUi) { + return; + } + pr.hasOverlayUi = hasOverlayUi; + //Slog.i(TAG, "Setting hasOverlayUi=" + pr.hasOverlayUi + " for pid=" + pid); + updateOomAdjLocked(pr); + } + } } private final class SleepTokenImpl extends SleepToken { diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index 356781fc7956..2d2720458fbb 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -31,14 +31,11 @@ import com.android.internal.os.BatteryStatsImpl; import android.app.ActivityManager; import android.app.Dialog; import android.app.IApplicationThread; -import android.app.IInstrumentationWatcher; -import android.app.IUiAutomationConnection; import android.content.ComponentName; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.res.CompatibilityInfo; import android.os.Binder; -import android.os.Bundle; import android.os.IBinder; import android.os.Process; import android.os.RemoteException; @@ -46,7 +43,6 @@ import android.os.SystemClock; import android.os.Trace; import android.os.UserHandle; import android.util.ArrayMap; -import android.util.PrintWriterPrinter; import android.util.TimeUtils; import java.io.PrintWriter; @@ -116,8 +112,18 @@ final class ProcessRecord { boolean repForegroundActivities; // Last reported foreground activities. boolean systemNoUi; // This is a system process, but not currently showing UI. boolean hasShownUi; // Has UI been shown in this process since it was started? - boolean hasTopUi; // Is this process currently showing "top-level" UI that is not an - // activity? + boolean hasTopUi; // Is this process currently showing a non-activity UI that the user + // is interacting with? E.g. The status bar when it is expanded, but + // not when it is minimized. When true the + // process will be set to use the ProcessList#SCHED_GROUP_TOP_APP + // scheduling group to boost performance. + boolean hasOverlayUi; // Is the process currently showing a non-activity UI that + // overlays on-top of activity UIs on screen. E.g. display a window + // of type + // android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY + // When true the process will oom adj score will be set to + // ProcessList#PERCEPTIBLE_APP_ADJ at minimum to reduce the chance + // of the process getting killed. boolean pendingUiClean; // Want to clean up resources from showing UI? boolean hasAboveClient; // Bound using BIND_ABOVE_CLIENT, so want to be lower boolean treatLikeActivity; // Bound using BIND_TREAT_LIKE_ACTIVITY @@ -425,6 +431,9 @@ final class ProcessRecord { if (hasTopUi) { pw.print(prefix); pw.print("hasTopUi="); pw.print(hasTopUi); } + if (hasOverlayUi) { + pw.print(prefix); pw.print("hasOverlayUi="); pw.print(hasOverlayUi); + } } ProcessRecord(BatteryStatsImpl _batteryStats, ApplicationInfo _info, diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index ead70e184e5c..782f9f2f6611 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -16,6 +16,7 @@ package com.android.server.wm; +import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING; import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS; @@ -69,6 +70,7 @@ public class Session extends IWindowSession.Stub private final String mStringName; SurfaceSession mSurfaceSession; private int mNumWindow = 0; + private int mNumOverlayWindow = 0; private boolean mClientDead = false; private float mLastReportedAnimatorScale; @@ -542,7 +544,7 @@ public class Session extends IWindowSession.Stub } } - void windowAddedLocked() { + void windowAddedLocked(int type) { if (mSurfaceSession == null) { if (WindowManagerService.localLOGV) Slog.v( TAG_WM, "First window added to " + this + ", creating SurfaceSession"); @@ -555,36 +557,56 @@ public class Session extends IWindowSession.Stub } } mNumWindow++; + if (type == TYPE_APPLICATION_OVERLAY) { + mNumOverlayWindow++; + setHasOverlayUi(true); + } } - void windowRemovedLocked() { + void windowRemovedLocked(int type) { mNumWindow--; + if (type == TYPE_APPLICATION_OVERLAY) { + mNumOverlayWindow--; + if (mNumOverlayWindow == 0) { + setHasOverlayUi(false); + } else if (mNumOverlayWindow < 0) { + throw new IllegalStateException("mNumOverlayWindow=" + mNumOverlayWindow + + " less than 0 for session=" + this); + } + } killSessionLocked(); } - void killSessionLocked() { - if (mNumWindow <= 0 && mClientDead) { - mService.mSessions.remove(this); - if (mSurfaceSession != null) { - if (WindowManagerService.localLOGV) Slog.v( - TAG_WM, "Last window removed from " + this - + ", destroying " + mSurfaceSession); - if (SHOW_TRANSACTIONS) Slog.i( - TAG_WM, " KILL SURFACE SESSION " + mSurfaceSession); - try { - mSurfaceSession.kill(); - } catch (Exception e) { - Slog.w(TAG_WM, "Exception thrown when killing surface session " - + mSurfaceSession + " in session " + this - + ": " + e.toString()); - } - mSurfaceSession = null; - } + private void killSessionLocked() { + if (mNumWindow > 0 || !mClientDead) { + return; } + + mService.mSessions.remove(this); + if (mSurfaceSession == null) { + return; + } + + if (WindowManagerService.localLOGV) Slog.v(TAG_WM, "Last window removed from " + this + + ", destroying " + mSurfaceSession); + if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, " KILL SURFACE SESSION " + mSurfaceSession); + try { + mSurfaceSession.kill(); + } catch (Exception e) { + Slog.w(TAG_WM, "Exception thrown when killing surface session " + mSurfaceSession + + " in session " + this + ": " + e.toString()); + } + mSurfaceSession = null; + setHasOverlayUi(false); + } + + private void setHasOverlayUi(boolean hasOverlayUi) { + mService.mH.obtainMessage(H.SET_HAS_OVERLAY_UI, mPid, hasOverlayUi ? 1 : 0).sendToTarget(); } void dump(PrintWriter pw, String prefix) { pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow); + pw.print(" mNumOverlayWindow="); pw.print(mNumOverlayWindow); pw.print(" mClientDead="); pw.print(mClientDead); pw.print(" mSurfaceSession="); pw.println(mSurfaceSession); } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index be0771ae97b5..1c864e8cf2e7 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -5268,6 +5268,7 @@ public class WindowManagerService extends IWindowManager.Stub public static final int RESTORE_POINTER_ICON = 55; public static final int NOTIFY_KEYGUARD_FLAGS_CHANGED = 56; public static final int NOTIFY_KEYGUARD_TRUSTED_CHANGED = 57; + public static final int SET_HAS_OVERLAY_UI = 58; /** * Used to denote that an integer field in a message will not be used. @@ -5751,6 +5752,10 @@ public class WindowManagerService extends IWindowManager.Stub mAmInternal.notifyKeyguardTrustedChanged(); } break; + case SET_HAS_OVERLAY_UI: { + mAmInternal.setHasOverlayUi(msg.arg1, msg.arg2 == 1); + } + break; } if (DEBUG_WINDOW_TRACE) { Slog.v(TAG_WM, "handleMessage: exit"); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 867080ed2450..65e1f84eae35 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -665,7 +665,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP void attach() { if (localLOGV) Slog.v(TAG, "Attaching " + this + " token=" + mToken); - mSession.windowAddedLocked(); + mSession.windowAddedLocked(mAttrs.type); } @Override @@ -1738,7 +1738,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mWinAnimator.destroyDeferredSurfaceLocked(); mWinAnimator.destroySurfaceLocked(); - mSession.windowRemovedLocked(); + mSession.windowRemovedLocked(mAttrs.type); try { mClient.asBinder().unlinkToDeath(mDeathRecipient, 0); } catch (RuntimeException e) { |