diff options
| -rw-r--r-- | services/core/java/com/android/server/display/DisplayManagerService.java | 83 | ||||
| -rw-r--r-- | services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java | 4 |
2 files changed, 59 insertions, 28 deletions
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index 0abd9bc3a433..2b732eab67cc 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 @@ public final class DisplayManagerService extends SystemService { 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 final class DisplayManagerService extends SystemService { public boolean mSafeMode; // All callback records indexed by calling process id. + @GuardedBy("mSyncRoot") private final SparseArray<CallbackRecord> mCallbacks = new SparseArray<>(); /** @@ -602,6 +604,7 @@ public final class DisplayManagerService extends SystemService { 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 @@ public final class DisplayManagerService extends SystemService { 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 @@ public final class DisplayManagerService extends SystemService { 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,34 +3240,38 @@ public final class DisplayManagerService extends SystemService { // 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); - } + 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); } + } else { + callbackRecord.notifyDisplayEventAsync(displayId, event); } - mTempCallbacks.clear(); } private boolean extraLogging(String packageName) { @@ -3764,7 +3776,7 @@ public final class DisplayManagerService extends SystemService { 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 @@ public final class DisplayManagerService extends SystemService { } /** - * @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 @@ public final class DisplayManagerService extends SystemService { "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 @@ public final class DisplayManagerService extends SystemService { } } + /** + * 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 026fcc486a92..5bb8ded6920e 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 static org.mockito.Mockito.when; 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 @@ public class DisplayManagerServiceTest { @Mock DisplayDeviceConfig mMockDisplayDeviceConfig; @Mock PackageManagerInternal mMockPackageManagerInternal; @Mock DisplayManagerInternal mMockDisplayManagerInternal; + @Mock ActivityManagerInternal mMockActivityManagerInternal; @Mock DisplayAdapter mMockDisplayAdapter; @Captor ArgumentCaptor<ContentRecordingSession> mContentRecordingSessionCaptor; @@ -388,6 +390,8 @@ public class DisplayManagerServiceTest { 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)); |