Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 93e85658 authored by David Riley's avatar David Riley
Browse files

Add batch update bindings API.

This will allow applications to reduce the number of calls to AMS when
multiple bindings need to be updated at once (e.g. for multi process
applications).  It will allow for a reduction in the number of
OomAdjuster updates and also allow for a small number of bindings
overall since bindings can be updated instead of having to use multiple
bindings as priorities change to services.

Changes include:
- Adding enable_update_service_bindings flag
- Adding Context.UpdateBindingParams
- Adding Context.updateServiceBindings via ActiveServices/ActivityManagerService
- Adding internal BindUpdateInfo interface
- Splitting up ActiveServices.unbindServiceLocked
- Adding ConnectionRecordInternal.updateFlags

Bug: 424003130
Flag: android.content.flags.enable_update_service_bindings
Test: atest android.app.cts.service.ServiceTest
Change-Id: If956709f5556e770a79345c0762c21181858e1ac
parent 14b4511c
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -11180,6 +11180,7 @@ package android.content {
    method @Nullable public abstract String getSystemServiceName(@NonNull Class<?>);
    method @NonNull public final CharSequence getText(@StringRes int);
    method public abstract android.content.res.Resources.Theme getTheme();
    method @FlaggedApi("android.content.flags.enable_update_service_bindings") @NonNull public android.content.Context.BindServiceFlags getUpdateableFlags();
    method @Deprecated public abstract android.graphics.drawable.Drawable getWallpaper();
    method @Deprecated public abstract int getWallpaperDesiredMinimumHeight();
    method @Deprecated public abstract int getWallpaperDesiredMinimumWidth();
@@ -11244,6 +11245,7 @@ package android.content {
    method public void unregisterComponentCallbacks(android.content.ComponentCallbacks);
    method public void unregisterDeviceIdChangeListener(@NonNull java.util.function.IntConsumer);
    method public abstract void unregisterReceiver(android.content.BroadcastReceiver);
    method @FlaggedApi("android.content.flags.enable_update_service_bindings") public void updateServiceBindings(@NonNull java.util.List<android.content.Context.UpdateBindingParams>);
    method public void updateServiceGroup(@NonNull android.content.ServiceConnection, int, int);
    field public static final String ACCESSIBILITY_SERVICE = "accessibility";
    field public static final String ACCOUNT_SERVICE = "account";
@@ -11387,6 +11389,21 @@ package android.content {
    method @NonNull public static android.content.Context.BindServiceFlags of(long);
  }
  @FlaggedApi("android.content.flags.enable_update_service_bindings") public static final class Context.UpdateBindingParams {
    method @NonNull public android.content.ServiceConnection getConnection();
    method @NonNull public android.content.Context.BindServiceFlags getFlags();
    method public boolean isRebind();
    method public boolean isUnbind();
    method public void setRebind(@NonNull android.content.Context.BindServiceFlags);
    method public void setUnbind();
  }
  public static final class Context.UpdateBindingParams.Builder {
    ctor public Context.UpdateBindingParams.Builder(@NonNull android.content.ServiceConnection);
    ctor public Context.UpdateBindingParams.Builder(@NonNull android.content.ServiceConnection, @NonNull android.content.Context.BindServiceFlags);
    method @NonNull public android.content.Context.UpdateBindingParams build();
  }
  public final class ContextParams {
    method @Nullable public String getAttributionTag();
    method @Nullable public android.content.AttributionSource getNextAttributionSource();
+6 −0
Original line number Diff line number Diff line
@@ -521,6 +521,11 @@ public abstract class ActivityManagerInternal {
     */
    public static final int OOM_ADJ_REASON_SERVICE_BINDER_CALL = 25;

    /**
     * Oom Adj Reason: Batched updated request.
     */
    public static final int OOM_ADJ_REASON_BATCH_UPDATE_REQUEST = 26;

    @IntDef(prefix = {"OOM_ADJ_REASON_"}, value = {
        OOM_ADJ_REASON_NONE,
        OOM_ADJ_REASON_ACTIVITY,
@@ -548,6 +553,7 @@ public abstract class ActivityManagerInternal {
        OOM_ADJ_REASON_FOLLOW_UP,
        OOM_ADJ_REASON_RECONFIGURATION,
        OOM_ADJ_REASON_SERVICE_BINDER_CALL,
        OOM_ADJ_REASON_BATCH_UPDATE_REQUEST,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface OomAdjReason {}
+24 −0
Original line number Diff line number Diff line
/*
 * Copyright 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 */
parcelable BindUpdateInfo {
  IBinder connection;
  boolean unbind;
  long flags;
}
+31 −0
Original line number Diff line number Diff line
@@ -2323,6 +2323,37 @@ class ContextImpl extends Context {
        }
    }

    @Override
    public void updateServiceBindings(@NonNull List<UpdateBindingParams> params) {
        final ArrayList<BindUpdateInfo> updates = new ArrayList<>(params.size());
        for (int i = 0, size = params.size(); i < size; i++) {
            final UpdateBindingParams param = params.get(i);
            final ServiceConnection conn = param.getConnection();
            if (conn == null) {
                throw new IllegalArgumentException("connection is null");
            }
            if (mPackageInfo == null) {
                throw new RuntimeException("Not supported in system context");
            }
            final IServiceConnection sd = mPackageInfo.lookupServiceDispatcher(
                            conn, getOuterContext());
            if (sd == null) {
                throw new IllegalArgumentException("ServiceConnection not currently bound: "
                        + conn);
            }
            final BindUpdateInfo update = new BindUpdateInfo();
            update.connection = sd.asBinder();
            update.unbind = param.isUnbind();
            update.flags = param.getFlags() != null ? param.getFlags().getValue() : 0;
            updates.add(update);
        }
        try {
            ActivityManager.getService().updateServiceBindings(updates);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    @Override
    public void unbindService(ServiceConnection conn) {
        if (conn == null) {
+2 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.app.ActivityTaskManager;
import android.app.ApplicationStartInfo;
import android.app.ApplicationErrorReport;
import android.app.ApplicationExitInfo;
import android.app.BindUpdateInfo;
import android.app.ContentProviderHolder;
import android.app.GrantedUriPermission;
import android.app.IApplicationStartInfoCompleteListener;
@@ -235,6 +236,7 @@ interface IActivityManager {
            in String resolvedType, in IServiceConnection connection, long flags,
            in String instanceName, in String callingPackage, int userId);
    void updateServiceGroup(in IServiceConnection connection, int group, int importance);
    void updateServiceBindings(in List<BindUpdateInfo> updates);
    @UnsupportedAppUsage
    boolean unbindService(in IServiceConnection connection);
    void publishService(in IBinder token, in IBinder bindToken, in IBinder service);
Loading