Loading core/java/android/os/BinderProxy.java +42 −0 Original line number Original line Diff line number Diff line Loading @@ -645,6 +645,37 @@ public final class BinderProxy implements IBinder { private native boolean unlinkToDeathNative(DeathRecipient recipient, int flags); private native boolean unlinkToDeathNative(DeathRecipient recipient, int flags); /** * This list is to hold strong reference to the frozen state callbacks. The callbacks are only * weakly referenced by JNI so the strong references here are needed to keep the callbacks * around until the proxy is GC'ed. */ private List<IFrozenStateChangeCallback> mFrozenStateChangeCallbacks = Collections.synchronizedList(new ArrayList<>()); /** * See {@link IBinder#addFrozenStateChangeCallback(IFrozenStateChangeCallback)} */ public void addFrozenStateChangeCallback(IFrozenStateChangeCallback callback) throws RemoteException { addFrozenStateChangeCallbackNative(callback); mFrozenStateChangeCallbacks.add(callback); } /** * See {@link IBinder#removeFrozenStateChangeCallback} */ public boolean removeFrozenStateChangeCallback(IFrozenStateChangeCallback callback) { mFrozenStateChangeCallbacks.remove(callback); return removeFrozenStateChangeCallbackNative(callback); } private native void addFrozenStateChangeCallbackNative(IFrozenStateChangeCallback callback) throws RemoteException; private native boolean removeFrozenStateChangeCallbackNative( IFrozenStateChangeCallback callback); /** /** * Perform a dump on the remote object * Perform a dump on the remote object * * Loading Loading @@ -730,6 +761,17 @@ public final class BinderProxy implements IBinder { } } } } private static void invokeFrozenStateChangeCallback( IFrozenStateChangeCallback callback, IBinder binderProxy, int stateIndex) { try { callback.onFrozenStateChanged(binderProxy, IFrozenStateChangeCallback.State.values()[stateIndex]); } catch (RuntimeException exc) { Log.w("BinderNative", "Uncaught exception from frozen state change callback", exc); } } /** /** * C++ pointer to BinderProxyNativeData. That consists of strong pointers to the * C++ pointer to BinderProxyNativeData. That consists of strong pointers to the * native IBinder object, and a DeathRecipientList. * native IBinder object, and a DeathRecipientList. Loading core/java/android/os/IBinder.java +49 −0 Original line number Original line Diff line number Diff line Loading @@ -376,4 +376,53 @@ public interface IBinder { * return value instead. * return value instead. */ */ public boolean unlinkToDeath(@NonNull DeathRecipient recipient, int flags); public boolean unlinkToDeath(@NonNull DeathRecipient recipient, int flags); /** @hide */ interface IFrozenStateChangeCallback { enum State {FROZEN, UNFROZEN}; /** * Interface for receiving a callback when the process hosting an IBinder * has changed its frozen state. * @param who The IBinder whose hosting process has changed state. * @param state The latest state. */ void onFrozenStateChanged(@NonNull IBinder who, State state); } /** * {@link addFrozenStateChangeCallback} provides a callback mechanism to notify about process * frozen/unfrozen events. Upon registration and any subsequent state changes, the callback is * invoked with the latest process frozen state. * * <p>If the listener process (the one using this API) is itself frozen, state change events * might be combined into a single one with the latest frozen state. This single event would * then be delivered when the listener process becomes unfrozen. Similarly, if an event happens * before the previous event is consumed, they might be combined. This means the callback might * not be called for every single state change, so don't rely on this API to count how many * times the state has changed.</p> * * <p>The callback is automatically removed when all references to the binder proxy are * dropped.</p> * * <p>You will only receive state change notifications for remote binders, as local binders by * definition can't be frozen without you being frozen too.</p> * * <p>@throws {@link UnsupportedOperationException} if the kernel binder driver does not support * this feature. * @hide */ default void addFrozenStateChangeCallback(@NonNull IFrozenStateChangeCallback callback) throws RemoteException { throw new UnsupportedOperationException(); } /** * Unregister a {@link IFrozenStateChangeCallback}. The callback will no longer be invoked when * the hosting process changes its frozen state. * @hide */ default boolean removeFrozenStateChangeCallback(@NonNull IFrozenStateChangeCallback callback) { throw new UnsupportedOperationException(); } } } core/jni/android_util_Binder.cpp +324 −122 File changed.Preview size limit exceeded, changes collapsed. Show changes core/tests/coretests/Android.bp +2 −0 Original line number Original line Diff line number Diff line Loading @@ -21,6 +21,7 @@ filegroup { srcs: [ srcs: [ "DisabledTestApp/src/**/*.java", "DisabledTestApp/src/**/*.java", "EnabledTestApp/src/**/*.java", "EnabledTestApp/src/**/*.java", "BinderFrozenStateChangeCallbackTestApp/src/**/*.java", "BinderProxyCountingTestApp/src/**/*.java", "BinderProxyCountingTestApp/src/**/*.java", "BinderProxyCountingTestService/src/**/*.java", "BinderProxyCountingTestService/src/**/*.java", "BinderDeathRecipientHelperApp/src/**/*.java", "BinderDeathRecipientHelperApp/src/**/*.java", Loading Loading @@ -134,6 +135,7 @@ android_test { ":BinderDeathRecipientHelperApp1", ":BinderDeathRecipientHelperApp1", ":BinderDeathRecipientHelperApp2", ":BinderDeathRecipientHelperApp2", ":com.android.cts.helpers.aosp", ":com.android.cts.helpers.aosp", ":BinderFrozenStateChangeCallbackTestApp", ":BinderProxyCountingTestApp", ":BinderProxyCountingTestApp", ":BinderProxyCountingTestService", ":BinderProxyCountingTestService", ], ], Loading core/tests/coretests/AndroidTest.xml +1 −0 Original line number Original line Diff line number Diff line Loading @@ -22,6 +22,7 @@ <option name="test-file-name" value="FrameworksCoreTests.apk" /> <option name="test-file-name" value="FrameworksCoreTests.apk" /> <option name="test-file-name" value="BinderDeathRecipientHelperApp1.apk" /> <option name="test-file-name" value="BinderDeathRecipientHelperApp1.apk" /> <option name="test-file-name" value="BinderDeathRecipientHelperApp2.apk" /> <option name="test-file-name" value="BinderDeathRecipientHelperApp2.apk" /> <option name="test-file-name" value="BinderFrozenStateChangeCallbackTestApp.apk" /> <option name="test-file-name" value="BinderProxyCountingTestApp.apk" /> <option name="test-file-name" value="BinderProxyCountingTestApp.apk" /> <option name="test-file-name" value="BinderProxyCountingTestService.apk" /> <option name="test-file-name" value="BinderProxyCountingTestService.apk" /> </target_preparer> </target_preparer> Loading Loading
core/java/android/os/BinderProxy.java +42 −0 Original line number Original line Diff line number Diff line Loading @@ -645,6 +645,37 @@ public final class BinderProxy implements IBinder { private native boolean unlinkToDeathNative(DeathRecipient recipient, int flags); private native boolean unlinkToDeathNative(DeathRecipient recipient, int flags); /** * This list is to hold strong reference to the frozen state callbacks. The callbacks are only * weakly referenced by JNI so the strong references here are needed to keep the callbacks * around until the proxy is GC'ed. */ private List<IFrozenStateChangeCallback> mFrozenStateChangeCallbacks = Collections.synchronizedList(new ArrayList<>()); /** * See {@link IBinder#addFrozenStateChangeCallback(IFrozenStateChangeCallback)} */ public void addFrozenStateChangeCallback(IFrozenStateChangeCallback callback) throws RemoteException { addFrozenStateChangeCallbackNative(callback); mFrozenStateChangeCallbacks.add(callback); } /** * See {@link IBinder#removeFrozenStateChangeCallback} */ public boolean removeFrozenStateChangeCallback(IFrozenStateChangeCallback callback) { mFrozenStateChangeCallbacks.remove(callback); return removeFrozenStateChangeCallbackNative(callback); } private native void addFrozenStateChangeCallbackNative(IFrozenStateChangeCallback callback) throws RemoteException; private native boolean removeFrozenStateChangeCallbackNative( IFrozenStateChangeCallback callback); /** /** * Perform a dump on the remote object * Perform a dump on the remote object * * Loading Loading @@ -730,6 +761,17 @@ public final class BinderProxy implements IBinder { } } } } private static void invokeFrozenStateChangeCallback( IFrozenStateChangeCallback callback, IBinder binderProxy, int stateIndex) { try { callback.onFrozenStateChanged(binderProxy, IFrozenStateChangeCallback.State.values()[stateIndex]); } catch (RuntimeException exc) { Log.w("BinderNative", "Uncaught exception from frozen state change callback", exc); } } /** /** * C++ pointer to BinderProxyNativeData. That consists of strong pointers to the * C++ pointer to BinderProxyNativeData. That consists of strong pointers to the * native IBinder object, and a DeathRecipientList. * native IBinder object, and a DeathRecipientList. Loading
core/java/android/os/IBinder.java +49 −0 Original line number Original line Diff line number Diff line Loading @@ -376,4 +376,53 @@ public interface IBinder { * return value instead. * return value instead. */ */ public boolean unlinkToDeath(@NonNull DeathRecipient recipient, int flags); public boolean unlinkToDeath(@NonNull DeathRecipient recipient, int flags); /** @hide */ interface IFrozenStateChangeCallback { enum State {FROZEN, UNFROZEN}; /** * Interface for receiving a callback when the process hosting an IBinder * has changed its frozen state. * @param who The IBinder whose hosting process has changed state. * @param state The latest state. */ void onFrozenStateChanged(@NonNull IBinder who, State state); } /** * {@link addFrozenStateChangeCallback} provides a callback mechanism to notify about process * frozen/unfrozen events. Upon registration and any subsequent state changes, the callback is * invoked with the latest process frozen state. * * <p>If the listener process (the one using this API) is itself frozen, state change events * might be combined into a single one with the latest frozen state. This single event would * then be delivered when the listener process becomes unfrozen. Similarly, if an event happens * before the previous event is consumed, they might be combined. This means the callback might * not be called for every single state change, so don't rely on this API to count how many * times the state has changed.</p> * * <p>The callback is automatically removed when all references to the binder proxy are * dropped.</p> * * <p>You will only receive state change notifications for remote binders, as local binders by * definition can't be frozen without you being frozen too.</p> * * <p>@throws {@link UnsupportedOperationException} if the kernel binder driver does not support * this feature. * @hide */ default void addFrozenStateChangeCallback(@NonNull IFrozenStateChangeCallback callback) throws RemoteException { throw new UnsupportedOperationException(); } /** * Unregister a {@link IFrozenStateChangeCallback}. The callback will no longer be invoked when * the hosting process changes its frozen state. * @hide */ default boolean removeFrozenStateChangeCallback(@NonNull IFrozenStateChangeCallback callback) { throw new UnsupportedOperationException(); } } }
core/jni/android_util_Binder.cpp +324 −122 File changed.Preview size limit exceeded, changes collapsed. Show changes
core/tests/coretests/Android.bp +2 −0 Original line number Original line Diff line number Diff line Loading @@ -21,6 +21,7 @@ filegroup { srcs: [ srcs: [ "DisabledTestApp/src/**/*.java", "DisabledTestApp/src/**/*.java", "EnabledTestApp/src/**/*.java", "EnabledTestApp/src/**/*.java", "BinderFrozenStateChangeCallbackTestApp/src/**/*.java", "BinderProxyCountingTestApp/src/**/*.java", "BinderProxyCountingTestApp/src/**/*.java", "BinderProxyCountingTestService/src/**/*.java", "BinderProxyCountingTestService/src/**/*.java", "BinderDeathRecipientHelperApp/src/**/*.java", "BinderDeathRecipientHelperApp/src/**/*.java", Loading Loading @@ -134,6 +135,7 @@ android_test { ":BinderDeathRecipientHelperApp1", ":BinderDeathRecipientHelperApp1", ":BinderDeathRecipientHelperApp2", ":BinderDeathRecipientHelperApp2", ":com.android.cts.helpers.aosp", ":com.android.cts.helpers.aosp", ":BinderFrozenStateChangeCallbackTestApp", ":BinderProxyCountingTestApp", ":BinderProxyCountingTestApp", ":BinderProxyCountingTestService", ":BinderProxyCountingTestService", ], ], Loading
core/tests/coretests/AndroidTest.xml +1 −0 Original line number Original line Diff line number Diff line Loading @@ -22,6 +22,7 @@ <option name="test-file-name" value="FrameworksCoreTests.apk" /> <option name="test-file-name" value="FrameworksCoreTests.apk" /> <option name="test-file-name" value="BinderDeathRecipientHelperApp1.apk" /> <option name="test-file-name" value="BinderDeathRecipientHelperApp1.apk" /> <option name="test-file-name" value="BinderDeathRecipientHelperApp2.apk" /> <option name="test-file-name" value="BinderDeathRecipientHelperApp2.apk" /> <option name="test-file-name" value="BinderFrozenStateChangeCallbackTestApp.apk" /> <option name="test-file-name" value="BinderProxyCountingTestApp.apk" /> <option name="test-file-name" value="BinderProxyCountingTestApp.apk" /> <option name="test-file-name" value="BinderProxyCountingTestService.apk" /> <option name="test-file-name" value="BinderProxyCountingTestService.apk" /> </target_preparer> </target_preparer> Loading