summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/ActivityManagerNative.java20
-rw-r--r--core/java/android/app/IActivityManager.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java24
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java44
-rw-r--r--services/core/java/com/android/server/am/ProcessRecord.java2
5 files changed, 97 insertions, 2 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 277348a318b9..aacd5da58640 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -3010,6 +3010,13 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
reply.writeNoException();
return true;
}
+ case SET_HAS_TOP_UI: {
+ data.enforceInterface(IActivityManager.descriptor);
+ final boolean hasTopUi = data.readInt() != 0;
+ setHasTopUi(hasTopUi);
+ reply.writeNoException();
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
@@ -7072,5 +7079,18 @@ class ActivityManagerProxy implements IActivityManager
return;
}
+ public void setHasTopUi(boolean hasTopUi)
+ throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeInt(hasTopUi ? 1 : 0);
+ mRemote.transact(SET_HAS_TOP_UI, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ return;
+ }
+
private IBinder mRemote;
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 4a4202aa4ce8..d54ce4bd3f05 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -661,6 +661,14 @@ public interface IActivityManager extends IInterface {
public void setVrThread(int tid) throws RemoteException;
public void setRenderThread(int tid) throws RemoteException;
+ /**
+ * Let's activity manager know whether the calling process is currently showing "top-level" UI
+ * that is not an activity, i.e. windows on the screen the user is currently interacting with.
+ *
+ * @param hasTopUi Whether the calling process has "top-level" UI.
+ */
+ public void setHasTopUi(boolean hasTopUi) throws RemoteException;
+
/*
* Private non-Binder interfaces
*/
@@ -1051,4 +1059,5 @@ public interface IActivityManager extends IInterface {
// Start of N MR1 transactions
int SET_VR_THREAD_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 377;
int SET_RENDER_THREAD_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 378;
+ int SET_HAS_TOP_UI = IBinder.FIRST_CALL_TRANSACTION + 379;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index 888e19c50f38..527148189588 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -16,11 +16,16 @@
package com.android.systemui.statusbar.phone;
+import android.app.ActivityManagerNative;
+import android.app.IActivityManager;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Resources;
import android.graphics.PixelFormat;
+import android.os.RemoteException;
import android.os.SystemProperties;
+import android.os.Trace;
+import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
@@ -41,11 +46,16 @@ import java.lang.reflect.Field;
*/
public class StatusBarWindowManager implements RemoteInputController.Callback {
+ private static final String TAG = "StatusBarWindowManager";
+
private final Context mContext;
private final WindowManager mWindowManager;
+ private final IActivityManager mActivityManager;
private View mStatusBarView;
private WindowManager.LayoutParams mLp;
private WindowManager.LayoutParams mLpChanged;
+ private boolean mHasTopUi;
+ private boolean mHasTopUiChanged;
private int mBarHeight;
private final boolean mKeyguardScreenRotation;
private final float mScreenBrightnessDoze;
@@ -54,6 +64,7 @@ public class StatusBarWindowManager implements RemoteInputController.Callback {
public StatusBarWindowManager(Context context) {
mContext = context;
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ mActivityManager = ActivityManagerNative.getDefault();
mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation();
mScreenBrightnessDoze = mContext.getResources().getInteger(
com.android.internal.R.integer.config_screenBrightnessDoze) / 255f;
@@ -193,9 +204,18 @@ public class StatusBarWindowManager implements RemoteInputController.Callback {
applyFitsSystemWindows(state);
applyModalFlag(state);
applyBrightness(state);
+ applyHasTopUi(state);
if (mLp.copyFrom(mLpChanged) != 0) {
mWindowManager.updateViewLayout(mStatusBarView, mLp);
}
+ if (mHasTopUi != mHasTopUiChanged) {
+ try {
+ mActivityManager.setHasTopUi(mHasTopUiChanged);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to call setHasTopUi", e);
+ }
+ mHasTopUi = mHasTopUiChanged;
+ }
}
private void applyForceStatusBarVisibleFlag(State state) {
@@ -224,6 +244,10 @@ public class StatusBarWindowManager implements RemoteInputController.Callback {
}
}
+ private void applyHasTopUi(State state) {
+ mHasTopUiChanged = isExpanded(state);
+ }
+
public void setKeyguardShowing(boolean showing) {
mCurrentState.keyguardShowing = showing;
apply(mCurrentState);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 59e309662302..236f083ab112 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -63,6 +63,7 @@ import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import android.Manifest;
+import android.Manifest.permission;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.Activity;
@@ -6280,6 +6281,9 @@ public final class ActivityManagerService extends ActivityManagerNative
enqueueUidChangeLocked(uidRec, -1, UidRecord.CHANGE_ACTIVE);
}
proc.uidRecord = uidRec;
+
+ // Reset render thread tid if it was already set, so new process can set it again.
+ proc.renderThreadTid = 0;
uidRec.numProcs++;
mProcessNames.put(proc.processName, proc.uid, proc);
if (proc.isolated) {
@@ -12672,6 +12676,42 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
+ @Override
+ public void setHasTopUi(boolean hasTopUi) throws RemoteException {
+ if (checkCallingPermission(permission.INTERNAL_SYSTEM_WINDOW) != PERMISSION_GRANTED) {
+ String msg = "Permission Denial: setHasTopUi() from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid()
+ + " requires " + permission.INTERNAL_SYSTEM_WINDOW;
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ }
+ final int pid = Binder.getCallingPid();
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ synchronized (this) {
+ boolean changed = false;
+ ProcessRecord pr;
+ synchronized (mPidsSelfLocked) {
+ pr = mPidsSelfLocked.get(pid);
+ if (pr == null) {
+ Slog.w(TAG, "setHasTopUi called on unknown pid: " + pid);
+ return;
+ }
+ if (pr.hasTopUi != hasTopUi) {
+ pr.hasTopUi = hasTopUi;
+ changed = true;
+ }
+ }
+ if (changed) {
+ updateOomAdjLocked(pr);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
public final void enterSafeMode() {
synchronized(this) {
// It only makes sense to do this before the system is ready
@@ -19148,7 +19188,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// facilitate this, here we need to determine whether or not it
// is currently showing UI.
app.systemNoUi = true;
- if (app == TOP_APP) {
+ if (app == TOP_APP || app.hasTopUi) {
app.systemNoUi = false;
app.curSchedGroup = ProcessList.SCHED_GROUP_TOP_APP;
app.adjType = "pers-top-activity";
@@ -19177,7 +19217,7 @@ public final class ActivityManagerService extends ActivityManagerNative
int procState;
boolean foregroundActivities = false;
BroadcastQueue queue;
- if (app == TOP_APP) {
+ if (app == TOP_APP || app.hasTopUi) {
// The last app on the list is the foreground app.
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index dad383dff22f..e74b3a32a2b8 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -116,6 +116,8 @@ 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 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