Loading services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java +24 −13 Original line number Original line Diff line number Diff line Loading @@ -117,6 +117,10 @@ public final class MediaProjectionManagerService extends SystemService // WindowManagerService -> MediaProjectionManagerService -> DisplayManagerService // WindowManagerService -> MediaProjectionManagerService -> DisplayManagerService // See mediaprojection.md // See mediaprojection.md private final Object mLock = new Object(); private final Object mLock = new Object(); // A handler for posting tasks that must interact with a service holding another lock, // especially for services that will eventually acquire the WindowManager lock. @NonNull private final Handler mHandler; private final Map<IBinder, IBinder.DeathRecipient> mDeathEaters; private final Map<IBinder, IBinder.DeathRecipient> mDeathEaters; private final CallbackDelegate mCallbackDelegate; private final CallbackDelegate mCallbackDelegate; Loading Loading @@ -145,6 +149,8 @@ public final class MediaProjectionManagerService extends SystemService super(context); super(context); mContext = context; mContext = context; mInjector = injector; mInjector = injector; // Post messages on the main thread; no need for a separate thread. mHandler = new Handler(Looper.getMainLooper()); mClock = injector.createClock(); mClock = injector.createClock(); mDeathEaters = new ArrayMap<IBinder, IBinder.DeathRecipient>(); mDeathEaters = new ArrayMap<IBinder, IBinder.DeathRecipient>(); mCallbackDelegate = new CallbackDelegate(injector.createCallbackLooper()); mCallbackDelegate = new CallbackDelegate(injector.createCallbackLooper()); Loading Loading @@ -243,7 +249,9 @@ public final class MediaProjectionManagerService extends SystemService if (!mProjectionGrant.requiresForegroundService()) { if (!mProjectionGrant.requiresForegroundService()) { return; return; } } } // Run outside the lock when calling into ActivityManagerService. if (mActivityManagerInternal.hasRunningForegroundService( if (mActivityManagerInternal.hasRunningForegroundService( uid, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION)) { uid, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION)) { // If there is any process within this UID running a FGS // If there is any process within this UID running a FGS Loading @@ -251,6 +259,7 @@ public final class MediaProjectionManagerService extends SystemService return; return; } } synchronized (mLock) { mProjectionGrant.stop(); mProjectionGrant.stop(); } } } } Loading Loading @@ -867,7 +876,6 @@ public final class MediaProjectionManagerService extends SystemService mTargetSdkVersion = targetSdkVersion; mTargetSdkVersion = targetSdkVersion; mIsPrivileged = isPrivileged; mIsPrivileged = isPrivileged; mCreateTimeMs = mClock.uptimeMillis(); mCreateTimeMs = mClock.uptimeMillis(); // TODO(b/267740338): Add unit test. mActivityManagerInternal.notifyMediaProjectionEvent(uid, asBinder(), mActivityManagerInternal.notifyMediaProjectionEvent(uid, asBinder(), MEDIA_PROJECTION_TOKEN_EVENT_CREATED); MEDIA_PROJECTION_TOKEN_EVENT_CREATED); } } Loading Loading @@ -924,6 +932,10 @@ public final class MediaProjectionManagerService extends SystemService if (callback == null) { if (callback == null) { throw new IllegalArgumentException("callback must not be null"); throw new IllegalArgumentException("callback must not be null"); } } // Cache result of calling into ActivityManagerService outside of the lock, to prevent // deadlock with WindowManagerService. final boolean hasFGS = mActivityManagerInternal.hasRunningForegroundService( uid, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION); synchronized (mLock) { synchronized (mLock) { if (isCurrentProjection(asBinder())) { if (isCurrentProjection(asBinder())) { Slog.w(TAG, "UID " + Binder.getCallingUid() Slog.w(TAG, "UID " + Binder.getCallingUid() Loading @@ -935,9 +947,7 @@ public final class MediaProjectionManagerService extends SystemService } } if (REQUIRE_FG_SERVICE_FOR_PROJECTION if (REQUIRE_FG_SERVICE_FOR_PROJECTION && requiresForegroundService() && requiresForegroundService() && !hasFGS) { && !mActivityManagerInternal.hasRunningForegroundService( uid, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION)) { throw new SecurityException("Media projections require a foreground service" throw new SecurityException("Media projections require a foreground service" + " of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION"); + " of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION"); } } Loading Loading @@ -1026,10 +1036,11 @@ public final class MediaProjectionManagerService extends SystemService mToken = null; mToken = null; unregisterCallback(mCallback); unregisterCallback(mCallback); mCallback = null; mCallback = null; // TODO(b/267740338): Add unit test. mActivityManagerInternal.notifyMediaProjectionEvent(uid, asBinder(), MEDIA_PROJECTION_TOKEN_EVENT_DESTROYED); } } // Run on a separate thread, to ensure no lock is held when calling into // ActivityManagerService. mHandler.post(() -> mActivityManagerInternal.notifyMediaProjectionEvent(uid, asBinder(), MEDIA_PROJECTION_TOKEN_EVENT_DESTROYED)); } } @Override // Binder call @Override // Binder call Loading services/core/java/com/android/server/media/projection/mediaprojection.md +5 −0 Original line number Original line Diff line number Diff line Loading @@ -11,6 +11,11 @@ Calls must follow the below invocation order while holding locks: `WindowManagerService -> MediaProjectionManagerService -> DisplayManagerService` `WindowManagerService -> MediaProjectionManagerService -> DisplayManagerService` `MediaProjectionManagerService` should never lock when calling into a service that may acquire the `WindowManagerService` global lock (for example, `MediaProjectionManagerService -> ActivityManagerService` may result in deadlock, since `ActivityManagerService -> WindowManagerService`). ### Justification ### Justification `MediaProjectionManagerService` calls into `WindowManagerService` in the below cases. While handling `MediaProjectionManagerService` calls into `WindowManagerService` in the below cases. While handling Loading Loading
services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java +24 −13 Original line number Original line Diff line number Diff line Loading @@ -117,6 +117,10 @@ public final class MediaProjectionManagerService extends SystemService // WindowManagerService -> MediaProjectionManagerService -> DisplayManagerService // WindowManagerService -> MediaProjectionManagerService -> DisplayManagerService // See mediaprojection.md // See mediaprojection.md private final Object mLock = new Object(); private final Object mLock = new Object(); // A handler for posting tasks that must interact with a service holding another lock, // especially for services that will eventually acquire the WindowManager lock. @NonNull private final Handler mHandler; private final Map<IBinder, IBinder.DeathRecipient> mDeathEaters; private final Map<IBinder, IBinder.DeathRecipient> mDeathEaters; private final CallbackDelegate mCallbackDelegate; private final CallbackDelegate mCallbackDelegate; Loading Loading @@ -145,6 +149,8 @@ public final class MediaProjectionManagerService extends SystemService super(context); super(context); mContext = context; mContext = context; mInjector = injector; mInjector = injector; // Post messages on the main thread; no need for a separate thread. mHandler = new Handler(Looper.getMainLooper()); mClock = injector.createClock(); mClock = injector.createClock(); mDeathEaters = new ArrayMap<IBinder, IBinder.DeathRecipient>(); mDeathEaters = new ArrayMap<IBinder, IBinder.DeathRecipient>(); mCallbackDelegate = new CallbackDelegate(injector.createCallbackLooper()); mCallbackDelegate = new CallbackDelegate(injector.createCallbackLooper()); Loading Loading @@ -243,7 +249,9 @@ public final class MediaProjectionManagerService extends SystemService if (!mProjectionGrant.requiresForegroundService()) { if (!mProjectionGrant.requiresForegroundService()) { return; return; } } } // Run outside the lock when calling into ActivityManagerService. if (mActivityManagerInternal.hasRunningForegroundService( if (mActivityManagerInternal.hasRunningForegroundService( uid, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION)) { uid, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION)) { // If there is any process within this UID running a FGS // If there is any process within this UID running a FGS Loading @@ -251,6 +259,7 @@ public final class MediaProjectionManagerService extends SystemService return; return; } } synchronized (mLock) { mProjectionGrant.stop(); mProjectionGrant.stop(); } } } } Loading Loading @@ -867,7 +876,6 @@ public final class MediaProjectionManagerService extends SystemService mTargetSdkVersion = targetSdkVersion; mTargetSdkVersion = targetSdkVersion; mIsPrivileged = isPrivileged; mIsPrivileged = isPrivileged; mCreateTimeMs = mClock.uptimeMillis(); mCreateTimeMs = mClock.uptimeMillis(); // TODO(b/267740338): Add unit test. mActivityManagerInternal.notifyMediaProjectionEvent(uid, asBinder(), mActivityManagerInternal.notifyMediaProjectionEvent(uid, asBinder(), MEDIA_PROJECTION_TOKEN_EVENT_CREATED); MEDIA_PROJECTION_TOKEN_EVENT_CREATED); } } Loading Loading @@ -924,6 +932,10 @@ public final class MediaProjectionManagerService extends SystemService if (callback == null) { if (callback == null) { throw new IllegalArgumentException("callback must not be null"); throw new IllegalArgumentException("callback must not be null"); } } // Cache result of calling into ActivityManagerService outside of the lock, to prevent // deadlock with WindowManagerService. final boolean hasFGS = mActivityManagerInternal.hasRunningForegroundService( uid, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION); synchronized (mLock) { synchronized (mLock) { if (isCurrentProjection(asBinder())) { if (isCurrentProjection(asBinder())) { Slog.w(TAG, "UID " + Binder.getCallingUid() Slog.w(TAG, "UID " + Binder.getCallingUid() Loading @@ -935,9 +947,7 @@ public final class MediaProjectionManagerService extends SystemService } } if (REQUIRE_FG_SERVICE_FOR_PROJECTION if (REQUIRE_FG_SERVICE_FOR_PROJECTION && requiresForegroundService() && requiresForegroundService() && !hasFGS) { && !mActivityManagerInternal.hasRunningForegroundService( uid, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION)) { throw new SecurityException("Media projections require a foreground service" throw new SecurityException("Media projections require a foreground service" + " of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION"); + " of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION"); } } Loading Loading @@ -1026,10 +1036,11 @@ public final class MediaProjectionManagerService extends SystemService mToken = null; mToken = null; unregisterCallback(mCallback); unregisterCallback(mCallback); mCallback = null; mCallback = null; // TODO(b/267740338): Add unit test. mActivityManagerInternal.notifyMediaProjectionEvent(uid, asBinder(), MEDIA_PROJECTION_TOKEN_EVENT_DESTROYED); } } // Run on a separate thread, to ensure no lock is held when calling into // ActivityManagerService. mHandler.post(() -> mActivityManagerInternal.notifyMediaProjectionEvent(uid, asBinder(), MEDIA_PROJECTION_TOKEN_EVENT_DESTROYED)); } } @Override // Binder call @Override // Binder call Loading
services/core/java/com/android/server/media/projection/mediaprojection.md +5 −0 Original line number Original line Diff line number Diff line Loading @@ -11,6 +11,11 @@ Calls must follow the below invocation order while holding locks: `WindowManagerService -> MediaProjectionManagerService -> DisplayManagerService` `WindowManagerService -> MediaProjectionManagerService -> DisplayManagerService` `MediaProjectionManagerService` should never lock when calling into a service that may acquire the `WindowManagerService` global lock (for example, `MediaProjectionManagerService -> ActivityManagerService` may result in deadlock, since `ActivityManagerService -> WindowManagerService`). ### Justification ### Justification `MediaProjectionManagerService` calls into `WindowManagerService` in the below cases. While handling `MediaProjectionManagerService` calls into `WindowManagerService` in the below cases. While handling Loading