Loading core/java/android/app/ActivityManagerInternal.java +6 −0 Original line number Diff line number Diff line Loading @@ -501,6 +501,11 @@ public abstract class ActivityManagerInternal { */ public static final int OOM_ADJ_REASON_RECONFIGURATION = 24; /** * Oom Adj Reason: Either a binder call has started or finished. */ public static final int OOM_ADJ_REASON_SERVICE_BINDER_CALL = 25; @IntDef(prefix = {"OOM_ADJ_REASON_"}, value = { OOM_ADJ_REASON_NONE, OOM_ADJ_REASON_ACTIVITY, Loading @@ -527,6 +532,7 @@ public abstract class ActivityManagerInternal { OOM_ADJ_REASON_COMPONENT_DISABLED, OOM_ADJ_REASON_FOLLOW_UP, OOM_ADJ_REASON_RECONFIGURATION, OOM_ADJ_REASON_SERVICE_BINDER_CALL, }) @Retention(RetentionPolicy.SOURCE) public @interface OomAdjReason {} Loading core/java/android/app/IBinderSession.aidl 0 → 100644 +23 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.app; /** @hide */ interface IBinderSession { long binderTransactionStarting(in String debugTag); void binderTransactionCompleted(in long token); } core/java/android/app/IServiceConnection.aidl +3 −2 Original line number Diff line number Diff line Loading @@ -17,11 +17,12 @@ package android.app; import android.app.IBinderSession; import android.content.ComponentName; /** @hide */ oneway interface IServiceConnection { @UnsupportedAppUsage void connected(in ComponentName name, IBinder service, boolean dead); void connected(in ComponentName name, IBinder service, in @nullable IBinderSession session, boolean dead); } core/java/android/app/LoadedApk.java +18 −13 Original line number Diff line number Diff line Loading @@ -2080,11 +2080,11 @@ public final class LoadedApk { mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd); } public void connected(ComponentName name, IBinder service, boolean dead) throws RemoteException { public void connected(ComponentName name, IBinder service, IBinderSession binderSession, boolean dead) throws RemoteException { LoadedApk.ServiceDispatcher sd = mDispatcher.get(); if (sd != null) { sd.connected(name, service, dead); sd.connected(name, service, binderSession, dead); } } } Loading Loading @@ -2172,27 +2172,29 @@ public final class LoadedApk { return mUnbindLocation; } public void connected(ComponentName name, IBinder service, boolean dead) { public void connected(ComponentName name, IBinder service, IBinderSession session, boolean dead) { if (mActivityExecutor != null) { mActivityExecutor.execute(new RunConnection(name, service, 0, dead)); mActivityExecutor.execute(new RunConnection(name, service, session, 0, dead)); } else if (mActivityThread != null) { mActivityThread.post(new RunConnection(name, service, 0, dead)); mActivityThread.post(new RunConnection(name, service, session, 0, dead)); } else { doConnected(name, service, dead); doConnected(name, service, session, dead); } } public void death(ComponentName name, IBinder service) { if (mActivityExecutor != null) { mActivityExecutor.execute(new RunConnection(name, service, 1, false)); mActivityExecutor.execute(new RunConnection(name, service, null, 1, false)); } else if (mActivityThread != null) { mActivityThread.post(new RunConnection(name, service, 1, false)); mActivityThread.post(new RunConnection(name, service, null, 1, false)); } else { doDeath(name, service); } } public void doConnected(ComponentName name, IBinder service, boolean dead) { public void doConnected(ComponentName name, IBinder service, IBinderSession session, boolean dead) { ServiceDispatcher.ConnectionInfo old; ServiceDispatcher.ConnectionInfo info; Loading Loading @@ -2242,7 +2244,7 @@ public final class LoadedApk { } else { // If there is a new viable service, it is now connected. if (service != null) { mConnection.onServiceConnected(name, service); mConnection.onServiceConnected(name, service, session); } else { // The binding machinery worked, but the remote returned null from onBind(). mConnection.onNullBinding(name); Loading @@ -2266,16 +2268,18 @@ public final class LoadedApk { } private final class RunConnection implements Runnable { RunConnection(ComponentName name, IBinder service, int command, boolean dead) { RunConnection(ComponentName name, IBinder service, IBinderSession session, int command, boolean dead) { mName = name; mService = service; mBinderSession = session; mCommand = command; mDead = dead; } public void run() { if (mCommand == 0) { doConnected(mName, mService, mDead); doConnected(mName, mService, mBinderSession, mDead); } else if (mCommand == 1) { doDeath(mName, mService); } Loading @@ -2283,6 +2287,7 @@ public final class LoadedApk { final ComponentName mName; final IBinder mService; final IBinderSession mBinderSession; final int mCommand; final boolean mDead; } Loading core/java/android/content/ServiceConnection.java +30 −0 Original line number Diff line number Diff line Loading @@ -16,7 +16,10 @@ package android.content; import android.annotation.Nullable; import android.app.IBinderSession; import android.os.IBinder; import android.util.Log; /** * Interface for monitoring the state of an application service. See Loading Loading @@ -44,6 +47,33 @@ public interface ServiceConnection { */ void onServiceConnected(ComponentName name, IBinder service); /** * Same as {@link #onServiceConnected(ComponentName, IBinder)} but provides a * {@link IBinderSession} to account for binder calls to a frozen remote process whenever the * {@link Context#BIND_ALLOW_FREEZE} was used with the bindService call. * * <p>Clients who do not use the {@link Context#BIND_ALLOW_FREEZE} flag can continue using * {@link #onServiceConnected(ComponentName, IBinder)} normally. Note that clients that use * {@link Context#BIND_ALLOW_FREEZE} but do not override this will have to deal with the remote * process's frozen state on their own. * * @param name The concrete component name of the service that has been connected. * @param service The IBinder of the Service's communication channel, which you can now make * calls on. * @param binderSession An IBinderSession used to keep the remote service unfrozen to process * any binder calls. Will be {@code null} when * {@link Context#BIND_ALLOW_FREEZE} was not used. * @hide */ default void onServiceConnected(ComponentName name, IBinder service, @Nullable IBinderSession binderSession) { if (binderSession != null) { final String tag = getClass().getSimpleName(); Log.w(tag, "Binder session present but potentially unused for binding to " + name); } onServiceConnected(name, service); } /** * Called when a connection to the Service has been lost. This typically * happens when the process hosting the service has crashed or been killed. Loading Loading
core/java/android/app/ActivityManagerInternal.java +6 −0 Original line number Diff line number Diff line Loading @@ -501,6 +501,11 @@ public abstract class ActivityManagerInternal { */ public static final int OOM_ADJ_REASON_RECONFIGURATION = 24; /** * Oom Adj Reason: Either a binder call has started or finished. */ public static final int OOM_ADJ_REASON_SERVICE_BINDER_CALL = 25; @IntDef(prefix = {"OOM_ADJ_REASON_"}, value = { OOM_ADJ_REASON_NONE, OOM_ADJ_REASON_ACTIVITY, Loading @@ -527,6 +532,7 @@ public abstract class ActivityManagerInternal { OOM_ADJ_REASON_COMPONENT_DISABLED, OOM_ADJ_REASON_FOLLOW_UP, OOM_ADJ_REASON_RECONFIGURATION, OOM_ADJ_REASON_SERVICE_BINDER_CALL, }) @Retention(RetentionPolicy.SOURCE) public @interface OomAdjReason {} Loading
core/java/android/app/IBinderSession.aidl 0 → 100644 +23 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.app; /** @hide */ interface IBinderSession { long binderTransactionStarting(in String debugTag); void binderTransactionCompleted(in long token); }
core/java/android/app/IServiceConnection.aidl +3 −2 Original line number Diff line number Diff line Loading @@ -17,11 +17,12 @@ package android.app; import android.app.IBinderSession; import android.content.ComponentName; /** @hide */ oneway interface IServiceConnection { @UnsupportedAppUsage void connected(in ComponentName name, IBinder service, boolean dead); void connected(in ComponentName name, IBinder service, in @nullable IBinderSession session, boolean dead); }
core/java/android/app/LoadedApk.java +18 −13 Original line number Diff line number Diff line Loading @@ -2080,11 +2080,11 @@ public final class LoadedApk { mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd); } public void connected(ComponentName name, IBinder service, boolean dead) throws RemoteException { public void connected(ComponentName name, IBinder service, IBinderSession binderSession, boolean dead) throws RemoteException { LoadedApk.ServiceDispatcher sd = mDispatcher.get(); if (sd != null) { sd.connected(name, service, dead); sd.connected(name, service, binderSession, dead); } } } Loading Loading @@ -2172,27 +2172,29 @@ public final class LoadedApk { return mUnbindLocation; } public void connected(ComponentName name, IBinder service, boolean dead) { public void connected(ComponentName name, IBinder service, IBinderSession session, boolean dead) { if (mActivityExecutor != null) { mActivityExecutor.execute(new RunConnection(name, service, 0, dead)); mActivityExecutor.execute(new RunConnection(name, service, session, 0, dead)); } else if (mActivityThread != null) { mActivityThread.post(new RunConnection(name, service, 0, dead)); mActivityThread.post(new RunConnection(name, service, session, 0, dead)); } else { doConnected(name, service, dead); doConnected(name, service, session, dead); } } public void death(ComponentName name, IBinder service) { if (mActivityExecutor != null) { mActivityExecutor.execute(new RunConnection(name, service, 1, false)); mActivityExecutor.execute(new RunConnection(name, service, null, 1, false)); } else if (mActivityThread != null) { mActivityThread.post(new RunConnection(name, service, 1, false)); mActivityThread.post(new RunConnection(name, service, null, 1, false)); } else { doDeath(name, service); } } public void doConnected(ComponentName name, IBinder service, boolean dead) { public void doConnected(ComponentName name, IBinder service, IBinderSession session, boolean dead) { ServiceDispatcher.ConnectionInfo old; ServiceDispatcher.ConnectionInfo info; Loading Loading @@ -2242,7 +2244,7 @@ public final class LoadedApk { } else { // If there is a new viable service, it is now connected. if (service != null) { mConnection.onServiceConnected(name, service); mConnection.onServiceConnected(name, service, session); } else { // The binding machinery worked, but the remote returned null from onBind(). mConnection.onNullBinding(name); Loading @@ -2266,16 +2268,18 @@ public final class LoadedApk { } private final class RunConnection implements Runnable { RunConnection(ComponentName name, IBinder service, int command, boolean dead) { RunConnection(ComponentName name, IBinder service, IBinderSession session, int command, boolean dead) { mName = name; mService = service; mBinderSession = session; mCommand = command; mDead = dead; } public void run() { if (mCommand == 0) { doConnected(mName, mService, mDead); doConnected(mName, mService, mBinderSession, mDead); } else if (mCommand == 1) { doDeath(mName, mService); } Loading @@ -2283,6 +2287,7 @@ public final class LoadedApk { final ComponentName mName; final IBinder mService; final IBinderSession mBinderSession; final int mCommand; final boolean mDead; } Loading
core/java/android/content/ServiceConnection.java +30 −0 Original line number Diff line number Diff line Loading @@ -16,7 +16,10 @@ package android.content; import android.annotation.Nullable; import android.app.IBinderSession; import android.os.IBinder; import android.util.Log; /** * Interface for monitoring the state of an application service. See Loading Loading @@ -44,6 +47,33 @@ public interface ServiceConnection { */ void onServiceConnected(ComponentName name, IBinder service); /** * Same as {@link #onServiceConnected(ComponentName, IBinder)} but provides a * {@link IBinderSession} to account for binder calls to a frozen remote process whenever the * {@link Context#BIND_ALLOW_FREEZE} was used with the bindService call. * * <p>Clients who do not use the {@link Context#BIND_ALLOW_FREEZE} flag can continue using * {@link #onServiceConnected(ComponentName, IBinder)} normally. Note that clients that use * {@link Context#BIND_ALLOW_FREEZE} but do not override this will have to deal with the remote * process's frozen state on their own. * * @param name The concrete component name of the service that has been connected. * @param service The IBinder of the Service's communication channel, which you can now make * calls on. * @param binderSession An IBinderSession used to keep the remote service unfrozen to process * any binder calls. Will be {@code null} when * {@link Context#BIND_ALLOW_FREEZE} was not used. * @hide */ default void onServiceConnected(ComponentName name, IBinder service, @Nullable IBinderSession binderSession) { if (binderSession != null) { final String tag = getClass().getSimpleName(); Log.w(tag, "Binder session present but potentially unused for binding to " + name); } onServiceConnected(name, service); } /** * Called when a connection to the Service has been lost. This typically * happens when the process hosting the service has crashed or been killed. Loading