Merge "Refactor DisplayManagerService" into main
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 0abd9bc..2b732ea 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -269,6 +269,7 @@
private final Context mContext;
private final DisplayManagerHandler mHandler;
+ private final HandlerExecutor mHandlerExecutor;
private final Handler mUiHandler;
private final DisplayModeDirector mDisplayModeDirector;
private final ExternalDisplayPolicy mExternalDisplayPolicy;
@@ -315,6 +316,7 @@
public boolean mSafeMode;
// All callback records indexed by calling process id.
+ @GuardedBy("mSyncRoot")
private final SparseArray<CallbackRecord> mCallbacks = new SparseArray<>();
/**
@@ -602,6 +604,7 @@
mContext = context;
mFlags = injector.getFlags();
mHandler = new DisplayManagerHandler(displayThreadLooper);
+ mHandlerExecutor = new HandlerExecutor(mHandler);
mUiHandler = UiThread.getHandler();
mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore);
mLogicalDisplayMapper = new LogicalDisplayMapper(mContext,
@@ -760,12 +763,13 @@
mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
+
ActivityManager activityManager = mContext.getSystemService(ActivityManager.class);
activityManager.addOnUidImportanceListener(mUidImportanceListener, IMPORTANCE_CACHED);
mDeviceStateManager = LocalServices.getService(DeviceStateManagerInternal.class);
mContext.getSystemService(DeviceStateManager.class).registerCallback(
- new HandlerExecutor(mHandler), new DeviceStateListener());
+ mHandlerExecutor, new DeviceStateListener());
mLogicalDisplayMapper.onWindowManagerReady();
scheduleTraversalLocked(false);
@@ -1019,6 +1023,10 @@
private class UidImportanceListener implements ActivityManager.OnUidImportanceListener {
@Override
public void onUidImportance(int uid, int importance) {
+ onUidImportanceInternal(uid, importance);
+ }
+
+ private void onUidImportanceInternal(int uid, int importance) {
synchronized (mPendingCallbackSelfLocked) {
if (importance >= IMPORTANCE_GONE) {
// Clean up as the app is already gone
@@ -3232,36 +3240,40 @@
// After releasing the lock, send the notifications out.
for (int i = 0; i < mTempCallbacks.size(); i++) {
CallbackRecord callbackRecord = mTempCallbacks.get(i);
- final int uid = callbackRecord.mUid;
- final int pid = callbackRecord.mPid;
- if (isUidCached(uid)) {
- // For cached apps, save the pending event until it becomes non-cached
- synchronized (mPendingCallbackSelfLocked) {
- SparseArray<PendingCallback> pendingCallbacks = mPendingCallbackSelfLocked.get(
- uid);
- if (extraLogging(callbackRecord.mPackageName)) {
- Slog.i(TAG, "Uid is cached: " + uid
- + ", pendingCallbacks: " + pendingCallbacks);
- }
- if (pendingCallbacks == null) {
- pendingCallbacks = new SparseArray<>();
- mPendingCallbackSelfLocked.put(uid, pendingCallbacks);
- }
- PendingCallback pendingCallback = pendingCallbacks.get(pid);
- if (pendingCallback == null) {
- pendingCallbacks.put(pid,
- new PendingCallback(callbackRecord, displayId, event));
- } else {
- pendingCallback.addDisplayEvent(displayId, event);
- }
- }
- } else {
- callbackRecord.notifyDisplayEventAsync(displayId, event);
- }
+ deliverEventInternal(callbackRecord, displayId, event);
}
mTempCallbacks.clear();
}
+ private void deliverEventInternal(CallbackRecord callbackRecord, int displayId, int event) {
+ final int uid = callbackRecord.mUid;
+ final int pid = callbackRecord.mPid;
+ if (isUidCached(uid)) {
+ // For cached apps, save the pending event until it becomes non-cached
+ synchronized (mPendingCallbackSelfLocked) {
+ SparseArray<PendingCallback> pendingCallbacks = mPendingCallbackSelfLocked.get(
+ uid);
+ if (extraLogging(callbackRecord.mPackageName)) {
+ Slog.i(TAG, "Uid is cached: " + uid
+ + ", pendingCallbacks: " + pendingCallbacks);
+ }
+ if (pendingCallbacks == null) {
+ pendingCallbacks = new SparseArray<>();
+ mPendingCallbackSelfLocked.put(uid, pendingCallbacks);
+ }
+ PendingCallback pendingCallback = pendingCallbacks.get(pid);
+ if (pendingCallback == null) {
+ pendingCallbacks.put(pid,
+ new PendingCallback(callbackRecord, displayId, event));
+ } else {
+ pendingCallback.addDisplayEvent(displayId, event);
+ }
+ }
+ } else {
+ callbackRecord.notifyDisplayEventAsync(displayId, event);
+ }
+ }
+
private boolean extraLogging(String packageName) {
return mExtraDisplayEventLogging && mExtraDisplayLoggingPackageName.equals(packageName);
}
@@ -3764,7 +3776,7 @@
public boolean mWifiDisplayScanRequested;
- CallbackRecord(int pid, int uid, IDisplayManagerCallback callback,
+ CallbackRecord(int pid, int uid, @NonNull IDisplayManagerCallback callback,
@EventsMask long eventsMask) {
mPid = pid;
mUid = uid;
@@ -3792,7 +3804,9 @@
}
/**
- * @return {@code false} if RemoteException happens; otherwise {@code true} for success.
+ * @return {@code false} if RemoteException happens; otherwise {@code true} for
+ * success. This returns true even if the event was deferred because the remote client is
+ * cached.
*/
public boolean notifyDisplayEventAsync(int displayId, @DisplayEvent int event) {
if (!shouldSendEvent(event)) {
@@ -3805,9 +3819,19 @@
"notifyDisplayEventAsync#notSendingEvent=" + event + ",mEventsMask="
+ mEventsMask);
}
+ // The client is not interested in this event, so do nothing.
return true;
}
+ return transmitDisplayEvent(displayId, event);
+ }
+
+ /**
+ * Transmit a single display event. The client is presumed ready. Return true on success
+ * and false if the client died.
+ */
+ private boolean transmitDisplayEvent(int displayId, @DisplayEvent int event) {
+ // The client is ready to receive the event.
try {
mCallback.onDisplayEvent(displayId, event);
return true;
@@ -3819,6 +3843,9 @@
}
}
+ /**
+ * Return true if the client is interested in this event.
+ */
private boolean shouldSendEvent(@DisplayEvent int event) {
final long mask = mEventsMask.get();
switch (event) {
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
index 026fcc4..5bb8ded 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -64,6 +64,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityManagerInternal;
import android.app.ActivityOptions.LaunchCookie;
import android.app.PropertyInvalidatedCache;
import android.companion.virtual.IVirtualDevice;
@@ -358,6 +359,7 @@
@Mock DisplayDeviceConfig mMockDisplayDeviceConfig;
@Mock PackageManagerInternal mMockPackageManagerInternal;
@Mock DisplayManagerInternal mMockDisplayManagerInternal;
+ @Mock ActivityManagerInternal mMockActivityManagerInternal;
@Mock DisplayAdapter mMockDisplayAdapter;
@Captor ArgumentCaptor<ContentRecordingSession> mContentRecordingSessionCaptor;
@@ -388,6 +390,8 @@
PackageManagerInternal.class, mMockPackageManagerInternal);
mLocalServiceKeeperRule.overrideLocalService(
DisplayManagerInternal.class, mMockDisplayManagerInternal);
+ mLocalServiceKeeperRule.overrideLocalService(
+ ActivityManagerInternal.class, mMockActivityManagerInternal);
Display display = mock(Display.class);
when(display.getDisplayAdjustments()).thenReturn(new DisplayAdjustments());
when(display.getBrightnessInfo()).thenReturn(mock(BrightnessInfo.class));