Loading core/java/android/os/BinderProxy.java +6 −0 Original line number Diff line number Diff line Loading @@ -687,12 +687,18 @@ public final class BinderProxy implements IBinder { return removeFrozenStateChangeCallbackNative(wrappedCallback); } public static boolean isFrozenStateChangeCallbackSupported() { return isFrozenStateChangeCallbackSupportedNative(); } private native void addFrozenStateChangeCallbackNative(FrozenStateChangeCallback callback) throws RemoteException; private native boolean removeFrozenStateChangeCallbackNative( FrozenStateChangeCallback callback); private static native boolean isFrozenStateChangeCallbackSupportedNative(); /** * Perform a dump on the remote object * Loading core/jni/android_util_Binder.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -1706,6 +1706,10 @@ static jboolean android_os_BinderProxy_removeFrozenStateChangeCallback(JNIEnv* e return res; } static jboolean android_os_BinderProxy_frozenStateChangeCallbackSupported(JNIEnv*, jclass*) { return ProcessState::isDriverFeatureEnabled(ProcessState::DriverFeature::FREEZE_NOTIFICATION); } static void BinderProxy_destroy(void* rawNativeData) { BinderProxyNativeData * nativeData = (BinderProxyNativeData *) rawNativeData; Loading Loading @@ -1750,6 +1754,8 @@ static const JNINativeMethod gBinderProxyMethods[] = { "(Landroid/os/IBinder$FrozenStateChangeCallback;)V", (void*)android_os_BinderProxy_addFrozenStateChangeCallback}, {"removeFrozenStateChangeCallbackNative", "(Landroid/os/IBinder$FrozenStateChangeCallback;)Z", (void*)android_os_BinderProxy_removeFrozenStateChangeCallback}, {"isFrozenStateChangeCallbackSupportedNative", "()Z", (void*)android_os_BinderProxy_frozenStateChangeCallbackSupported}, {"getNativeFinalizer", "()J", (void*)android_os_BinderProxy_getNativeFinalizer}, {"getExtension", "()Landroid/os/IBinder;", (void*)android_os_BinderProxy_getExtension}, }; Loading services/core/java/com/android/server/display/DisplayManagerService.java +40 −41 Original line number Diff line number Diff line Loading @@ -119,6 +119,7 @@ import android.os.Handler; import android.os.HandlerExecutor; import android.os.IBinder; import android.os.IBinder.DeathRecipient; import android.os.IBinder.FrozenStateChangeCallback; import android.os.IThermalService; import android.os.Looper; import android.os.Message; Loading Loading @@ -272,6 +273,7 @@ public final class DisplayManagerService extends SystemService { private static final int MSG_DELIVER_DISPLAY_EVENT_FRAME_RATE_OVERRIDE = 7; private static final int MSG_DELIVER_DISPLAY_GROUP_EVENT = 8; private static final int MSG_RECEIVED_DEVICE_STATE = 9; private static final int MSG_DISPATCH_PENDING_PROCESS_EVENTS = 10; private static final int[] EMPTY_ARRAY = new int[0]; private static final HdrConversionMode HDR_CONVERSION_MODE_UNSUPPORTED = new HdrConversionMode( HDR_CONVERSION_UNSUPPORTED); Loading @@ -286,7 +288,6 @@ public final class DisplayManagerService extends SystemService { private InputManagerInternal mInputManagerInternal; private ActivityManagerInternal mActivityManagerInternal; private final UidImportanceListener mUidImportanceListener = new UidImportanceListener(); private final DisplayFrozenProcessListener mDisplayFrozenProcessListener; @Nullable private IMediaProjectionManager mProjectionService; Loading Loading @@ -630,7 +631,6 @@ public final class DisplayManagerService extends SystemService { mFlags = injector.getFlags(); mHandler = new DisplayManagerHandler(displayThreadLooper); mHandlerExecutor = new HandlerExecutor(mHandler); mDisplayFrozenProcessListener = new DisplayFrozenProcessListener(); mUiHandler = UiThread.getHandler(); mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore); mLogicalDisplayMapper = new LogicalDisplayMapper(mContext, Loading Loading @@ -1165,31 +1165,11 @@ public final class DisplayManagerService extends SystemService { } } private class DisplayFrozenProcessListener implements ActivityManagerInternal.FrozenProcessListener { public void onProcessFrozen(int pid) { synchronized (mSyncRoot) { CallbackRecord callback = mCallbacks.get(pid); if (callback == null) { return; } callback.setFrozen(true); } } public void onProcessUnfrozen(int pid) { // First, see if there is a callback associated with this pid. If there's no // callback, then there is nothing to do. CallbackRecord callback; synchronized (mSyncRoot) { callback = mCallbacks.get(pid); if (callback == null) { return; } callback.setFrozen(false); } // Attempt to dispatch pending events if the process is coming out of frozen. private void dispatchPendingProcessEvents(@NonNull Object cb) { if (cb instanceof CallbackRecord callback) { callback.dispatchPending(); } else { Slog.wtf(TAG, "not a callback: " + cb); } } Loading Loading @@ -4052,6 +4032,9 @@ public final class DisplayManagerService extends SystemService { deliverDisplayGroupEvent(msg.arg1, msg.arg2); break; case MSG_DISPATCH_PENDING_PROCESS_EVENTS: dispatchPendingProcessEvents(msg.obj); break; } } } Loading Loading @@ -4119,7 +4102,7 @@ public final class DisplayManagerService extends SystemService { } } private final class CallbackRecord implements DeathRecipient { private final class CallbackRecord implements DeathRecipient, FrozenStateChangeCallback { public final int mPid; public final int mUid; private final IDisplayManagerCallback mCallback; Loading @@ -4142,6 +4125,8 @@ public final class DisplayManagerService extends SystemService { private boolean mCached; @GuardedBy("mCallback") private boolean mFrozen; @GuardedBy("mCallback") private boolean mAlive; CallbackRecord(int pid, int uid, @NonNull IDisplayManagerCallback callback, @InternalEventFlag long internalEventFlagsMask) { Loading @@ -4151,18 +4136,20 @@ public final class DisplayManagerService extends SystemService { mInternalEventFlagsMask = new AtomicLong(internalEventFlagsMask); mCached = false; mFrozen = false; mAlive = true; if (deferDisplayEventsWhenFrozen()) { // Some CallbackRecords are registered very early in system boot, before // mActivityManagerInternal is initialized. If mActivityManagerInternal is null, // do not register the frozen process listener. However, do verify that all such // registrations are for the self pid (which can never be frozen, so the frozen // process listener does not matter). if (mActivityManagerInternal != null) { mActivityManagerInternal.addFrozenProcessListener(pid, mHandlerExecutor, mDisplayFrozenProcessListener); } else if (Process.myPid() != pid) { Slog.e(TAG, "DisplayListener registered too early"); try { callback.asBinder().addFrozenStateChangeCallback(this); } catch (UnsupportedOperationException e) { // Ignore the exception. The callback is not supported on this platform or on // this binder. The callback is never supported for local binders. There is // no error: the UID importance listener will still operate. A log message is // provided for debug. Slog.v(TAG, "FrozenStateChangeCallback not supported for pid " + mPid); } catch (RemoteException e) { // This is unexpected. Just give up. throw new RuntimeException(e); } } Loading @@ -4187,7 +4174,7 @@ public final class DisplayManagerService extends SystemService { */ @GuardedBy("mCallback") private boolean hasPendingAndIsReadyLocked() { return isReadyLocked() && mPendingEvents != null && !mPendingEvents.isEmpty(); return isReadyLocked() && mPendingEvents != null && !mPendingEvents.isEmpty() && mAlive; } /** Loading @@ -4195,7 +4182,7 @@ public final class DisplayManagerService extends SystemService { * receive events and there are pending events to be delivered. * This is only used if {@link deferDisplayEventsWhenFrozen()} is true. */ public boolean setFrozen(boolean frozen) { private boolean setFrozen(boolean frozen) { synchronized (mCallback) { mFrozen = frozen; return hasPendingAndIsReadyLocked(); Loading @@ -4216,6 +4203,9 @@ public final class DisplayManagerService extends SystemService { @Override public void binderDied() { synchronized (mCallback) { mAlive = false; } if (DEBUG || extraLogging(mPackageName)) { Slog.d(TAG, "Display listener for pid " + mPid + " died."); } Loading @@ -4226,6 +4216,14 @@ public final class DisplayManagerService extends SystemService { onCallbackDied(this); } @Override public void onFrozenStateChanged(@NonNull IBinder who, int state) { if (setFrozen(state == FrozenStateChangeCallback.STATE_FROZEN)) { Message msg = mHandler.obtainMessage(MSG_DISPATCH_PENDING_PROCESS_EVENTS, this); mHandler.sendMessage(msg); } } /** * @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 Loading Loading @@ -4392,7 +4390,7 @@ public final class DisplayManagerService extends SystemService { // This is only used if {@link deferDisplayEventsWhenFrozen()} is true. public boolean dispatchPending() { synchronized (mCallback) { if (mPendingEvents == null || mPendingEvents.isEmpty()) { if (mPendingEvents == null || mPendingEvents.isEmpty() || !mAlive) { return true; } if (!isReadyLocked()) { Loading Loading @@ -6064,6 +6062,7 @@ public final class DisplayManagerService extends SystemService { * Return the value of the pause */ private static boolean deferDisplayEventsWhenFrozen() { return com.android.server.am.Flags.deferDisplayEventsWhenFrozen(); return android.os.Flags.binderFrozenStateChangeCallback() && com.android.server.am.Flags.deferDisplayEventsWhenFrozen(); } } services/tests/displayservicetests/src/com/android/server/display/DisplayEventDeliveryTest.java +7 −2 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.content.Context; import android.content.Intent; import android.hardware.display.DisplayManager; import android.hardware.display.VirtualDisplay; import android.os.BinderProxy; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; Loading Loading @@ -290,11 +291,15 @@ public class DisplayEventDeliveryTest { } /** * Return true if the freezer is enabled on this platform. * Return true if the freezer is enabled on this platform and if freezer notifications are * supported. It is not enough to test that the freezer notification feature is enabled * because some devices do not have the necessary kernel support. */ private boolean isAppFreezerEnabled() { try { return mActivityManager.getService().isAppFreezerEnabled(); return mActivityManager.getService().isAppFreezerEnabled() && android.os.Flags.binderFrozenStateChangeCallback() && BinderProxy.isFrozenStateChangeCallbackSupported(); } catch (Exception e) { Log.e(TAG, "isAppFreezerEnabled() failed: " + e); return false; Loading Loading
core/java/android/os/BinderProxy.java +6 −0 Original line number Diff line number Diff line Loading @@ -687,12 +687,18 @@ public final class BinderProxy implements IBinder { return removeFrozenStateChangeCallbackNative(wrappedCallback); } public static boolean isFrozenStateChangeCallbackSupported() { return isFrozenStateChangeCallbackSupportedNative(); } private native void addFrozenStateChangeCallbackNative(FrozenStateChangeCallback callback) throws RemoteException; private native boolean removeFrozenStateChangeCallbackNative( FrozenStateChangeCallback callback); private static native boolean isFrozenStateChangeCallbackSupportedNative(); /** * Perform a dump on the remote object * Loading
core/jni/android_util_Binder.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -1706,6 +1706,10 @@ static jboolean android_os_BinderProxy_removeFrozenStateChangeCallback(JNIEnv* e return res; } static jboolean android_os_BinderProxy_frozenStateChangeCallbackSupported(JNIEnv*, jclass*) { return ProcessState::isDriverFeatureEnabled(ProcessState::DriverFeature::FREEZE_NOTIFICATION); } static void BinderProxy_destroy(void* rawNativeData) { BinderProxyNativeData * nativeData = (BinderProxyNativeData *) rawNativeData; Loading Loading @@ -1750,6 +1754,8 @@ static const JNINativeMethod gBinderProxyMethods[] = { "(Landroid/os/IBinder$FrozenStateChangeCallback;)V", (void*)android_os_BinderProxy_addFrozenStateChangeCallback}, {"removeFrozenStateChangeCallbackNative", "(Landroid/os/IBinder$FrozenStateChangeCallback;)Z", (void*)android_os_BinderProxy_removeFrozenStateChangeCallback}, {"isFrozenStateChangeCallbackSupportedNative", "()Z", (void*)android_os_BinderProxy_frozenStateChangeCallbackSupported}, {"getNativeFinalizer", "()J", (void*)android_os_BinderProxy_getNativeFinalizer}, {"getExtension", "()Landroid/os/IBinder;", (void*)android_os_BinderProxy_getExtension}, }; Loading
services/core/java/com/android/server/display/DisplayManagerService.java +40 −41 Original line number Diff line number Diff line Loading @@ -119,6 +119,7 @@ import android.os.Handler; import android.os.HandlerExecutor; import android.os.IBinder; import android.os.IBinder.DeathRecipient; import android.os.IBinder.FrozenStateChangeCallback; import android.os.IThermalService; import android.os.Looper; import android.os.Message; Loading Loading @@ -272,6 +273,7 @@ public final class DisplayManagerService extends SystemService { private static final int MSG_DELIVER_DISPLAY_EVENT_FRAME_RATE_OVERRIDE = 7; private static final int MSG_DELIVER_DISPLAY_GROUP_EVENT = 8; private static final int MSG_RECEIVED_DEVICE_STATE = 9; private static final int MSG_DISPATCH_PENDING_PROCESS_EVENTS = 10; private static final int[] EMPTY_ARRAY = new int[0]; private static final HdrConversionMode HDR_CONVERSION_MODE_UNSUPPORTED = new HdrConversionMode( HDR_CONVERSION_UNSUPPORTED); Loading @@ -286,7 +288,6 @@ public final class DisplayManagerService extends SystemService { private InputManagerInternal mInputManagerInternal; private ActivityManagerInternal mActivityManagerInternal; private final UidImportanceListener mUidImportanceListener = new UidImportanceListener(); private final DisplayFrozenProcessListener mDisplayFrozenProcessListener; @Nullable private IMediaProjectionManager mProjectionService; Loading Loading @@ -630,7 +631,6 @@ public final class DisplayManagerService extends SystemService { mFlags = injector.getFlags(); mHandler = new DisplayManagerHandler(displayThreadLooper); mHandlerExecutor = new HandlerExecutor(mHandler); mDisplayFrozenProcessListener = new DisplayFrozenProcessListener(); mUiHandler = UiThread.getHandler(); mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore); mLogicalDisplayMapper = new LogicalDisplayMapper(mContext, Loading Loading @@ -1165,31 +1165,11 @@ public final class DisplayManagerService extends SystemService { } } private class DisplayFrozenProcessListener implements ActivityManagerInternal.FrozenProcessListener { public void onProcessFrozen(int pid) { synchronized (mSyncRoot) { CallbackRecord callback = mCallbacks.get(pid); if (callback == null) { return; } callback.setFrozen(true); } } public void onProcessUnfrozen(int pid) { // First, see if there is a callback associated with this pid. If there's no // callback, then there is nothing to do. CallbackRecord callback; synchronized (mSyncRoot) { callback = mCallbacks.get(pid); if (callback == null) { return; } callback.setFrozen(false); } // Attempt to dispatch pending events if the process is coming out of frozen. private void dispatchPendingProcessEvents(@NonNull Object cb) { if (cb instanceof CallbackRecord callback) { callback.dispatchPending(); } else { Slog.wtf(TAG, "not a callback: " + cb); } } Loading Loading @@ -4052,6 +4032,9 @@ public final class DisplayManagerService extends SystemService { deliverDisplayGroupEvent(msg.arg1, msg.arg2); break; case MSG_DISPATCH_PENDING_PROCESS_EVENTS: dispatchPendingProcessEvents(msg.obj); break; } } } Loading Loading @@ -4119,7 +4102,7 @@ public final class DisplayManagerService extends SystemService { } } private final class CallbackRecord implements DeathRecipient { private final class CallbackRecord implements DeathRecipient, FrozenStateChangeCallback { public final int mPid; public final int mUid; private final IDisplayManagerCallback mCallback; Loading @@ -4142,6 +4125,8 @@ public final class DisplayManagerService extends SystemService { private boolean mCached; @GuardedBy("mCallback") private boolean mFrozen; @GuardedBy("mCallback") private boolean mAlive; CallbackRecord(int pid, int uid, @NonNull IDisplayManagerCallback callback, @InternalEventFlag long internalEventFlagsMask) { Loading @@ -4151,18 +4136,20 @@ public final class DisplayManagerService extends SystemService { mInternalEventFlagsMask = new AtomicLong(internalEventFlagsMask); mCached = false; mFrozen = false; mAlive = true; if (deferDisplayEventsWhenFrozen()) { // Some CallbackRecords are registered very early in system boot, before // mActivityManagerInternal is initialized. If mActivityManagerInternal is null, // do not register the frozen process listener. However, do verify that all such // registrations are for the self pid (which can never be frozen, so the frozen // process listener does not matter). if (mActivityManagerInternal != null) { mActivityManagerInternal.addFrozenProcessListener(pid, mHandlerExecutor, mDisplayFrozenProcessListener); } else if (Process.myPid() != pid) { Slog.e(TAG, "DisplayListener registered too early"); try { callback.asBinder().addFrozenStateChangeCallback(this); } catch (UnsupportedOperationException e) { // Ignore the exception. The callback is not supported on this platform or on // this binder. The callback is never supported for local binders. There is // no error: the UID importance listener will still operate. A log message is // provided for debug. Slog.v(TAG, "FrozenStateChangeCallback not supported for pid " + mPid); } catch (RemoteException e) { // This is unexpected. Just give up. throw new RuntimeException(e); } } Loading @@ -4187,7 +4174,7 @@ public final class DisplayManagerService extends SystemService { */ @GuardedBy("mCallback") private boolean hasPendingAndIsReadyLocked() { return isReadyLocked() && mPendingEvents != null && !mPendingEvents.isEmpty(); return isReadyLocked() && mPendingEvents != null && !mPendingEvents.isEmpty() && mAlive; } /** Loading @@ -4195,7 +4182,7 @@ public final class DisplayManagerService extends SystemService { * receive events and there are pending events to be delivered. * This is only used if {@link deferDisplayEventsWhenFrozen()} is true. */ public boolean setFrozen(boolean frozen) { private boolean setFrozen(boolean frozen) { synchronized (mCallback) { mFrozen = frozen; return hasPendingAndIsReadyLocked(); Loading @@ -4216,6 +4203,9 @@ public final class DisplayManagerService extends SystemService { @Override public void binderDied() { synchronized (mCallback) { mAlive = false; } if (DEBUG || extraLogging(mPackageName)) { Slog.d(TAG, "Display listener for pid " + mPid + " died."); } Loading @@ -4226,6 +4216,14 @@ public final class DisplayManagerService extends SystemService { onCallbackDied(this); } @Override public void onFrozenStateChanged(@NonNull IBinder who, int state) { if (setFrozen(state == FrozenStateChangeCallback.STATE_FROZEN)) { Message msg = mHandler.obtainMessage(MSG_DISPATCH_PENDING_PROCESS_EVENTS, this); mHandler.sendMessage(msg); } } /** * @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 Loading Loading @@ -4392,7 +4390,7 @@ public final class DisplayManagerService extends SystemService { // This is only used if {@link deferDisplayEventsWhenFrozen()} is true. public boolean dispatchPending() { synchronized (mCallback) { if (mPendingEvents == null || mPendingEvents.isEmpty()) { if (mPendingEvents == null || mPendingEvents.isEmpty() || !mAlive) { return true; } if (!isReadyLocked()) { Loading Loading @@ -6064,6 +6062,7 @@ public final class DisplayManagerService extends SystemService { * Return the value of the pause */ private static boolean deferDisplayEventsWhenFrozen() { return com.android.server.am.Flags.deferDisplayEventsWhenFrozen(); return android.os.Flags.binderFrozenStateChangeCallback() && com.android.server.am.Flags.deferDisplayEventsWhenFrozen(); } }
services/tests/displayservicetests/src/com/android/server/display/DisplayEventDeliveryTest.java +7 −2 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.content.Context; import android.content.Intent; import android.hardware.display.DisplayManager; import android.hardware.display.VirtualDisplay; import android.os.BinderProxy; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; Loading Loading @@ -290,11 +291,15 @@ public class DisplayEventDeliveryTest { } /** * Return true if the freezer is enabled on this platform. * Return true if the freezer is enabled on this platform and if freezer notifications are * supported. It is not enough to test that the freezer notification feature is enabled * because some devices do not have the necessary kernel support. */ private boolean isAppFreezerEnabled() { try { return mActivityManager.getService().isAppFreezerEnabled(); return mActivityManager.getService().isAppFreezerEnabled() && android.os.Flags.binderFrozenStateChangeCallback() && BinderProxy.isFrozenStateChangeCallbackSupported(); } catch (Exception e) { Log.e(TAG, "isAppFreezerEnabled() failed: " + e); return false; Loading