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

Commit fb643f64 authored by juquan's avatar juquan Committed by Cintia Martins
Browse files

SupervisionAppService Binding.

Bug: 392836577
Flag: android.app.supervision.flags.enable_supervision_app_service
Test: CtsAppBindingHostTestCases
Change-Id: I1887222319a72c61e81d046c7607ee51bef29c05
parent 06722d90
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -112,7 +112,6 @@ aconfig_declarations_group {
        "com.android.window.flags.window-aconfig-java",
        "configinfra_framework_flags_java_exported_lib",
        "conscrypt_exported_aconfig_flags_lib",
        "sdk_sandbox_exported_flags_lib",
        "device_policy_aconfig_flags_lib",
        "display_flags_lib",
        "dropbox_flags_lib",
@@ -126,6 +125,7 @@ aconfig_declarations_group {
        "libcore_readonly_aconfig_flags_lib",
        "libgui_flags_java_lib",
        "power_flags_lib",
        "sdk_sandbox_exported_flags_lib",
        "surfaceflinger_flags_java_lib",
        "telecom_flags_core_java_lib",
        "telephony_flags_core_java_lib",
@@ -868,9 +868,9 @@ java_aconfig_library {
    min_sdk_version: "30",
    apex_available: [
        "//apex_available:platform",
        "com.android.extservices",
        "com.android.nfcservices",
        "com.android.permission",
        "com.android.extservices",
    ],
}

@@ -1438,6 +1438,13 @@ java_aconfig_library {
    defaults: ["framework-minus-apex-aconfig-java-defaults"],
}

java_aconfig_library {
    name: "android.app.supervision.flags-aconfig-java-host",
    aconfig_declarations: "android.app.supervision.flags-aconfig",
    host_supported: true,
    defaults: ["framework-minus-apex-aconfig-java-defaults"],
}

// SurfaceFlinger
java_aconfig_library {
    name: "surfaceflinger_flags_java_lib",
+12 −0
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package android.app.supervision;

import android.annotation.FlaggedApi;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.app.Service;
import android.app.supervision.flags.Flags;
@@ -33,6 +35,16 @@ import android.os.IBinder;
@SystemApi
@FlaggedApi(Flags.FLAG_ENABLE_SUPERVISION_APP_SERVICE)
public class SupervisionAppService extends Service {
    /**
     * Service action: Action for a service that the {@code
     * android.app.role.RoleManager.ROLE_SYSTEM_SUPERVISION} role holder must implement.
     *
     * @hide
     */
    @SdkConstant(SdkConstantType.SERVICE_ACTION)
    public static final String ACTION_BIND_SUPERVISION_APP_SERVICE =
            "android.app.action.BIND_SUPERVISION_APP_SERVICE";

    private final ISupervisionAppService mBinder =
            new ISupervisionAppService.Stub() {
                @Override
+30 −0
Original line number Diff line number Diff line
@@ -46,6 +46,12 @@ public class AppBindingConstants {
    private static final String SMS_APP_BIND_FLAGS_KEY =
            "sms_app_bind_flags";

    private static final String SUPERVISION_APP_SERVICE_ENABLED_KEY =
            "supervision_app_service_enabled";

    private static final String SUPERVISION_APP_SERVICE_BIND_FLAGS_KEY =
            "supervision_app_service_bind_flags";

    public final String sourceSettings;

    /**
@@ -79,6 +85,12 @@ public class AppBindingConstants {
     */
    public final int SMS_APP_BIND_FLAGS;

    /** Whether to actually bind to the supervision app service. (Feature flag) */
    public final boolean SUPERVISION_APP_SERVICE_ENABLED;

    /** Extra binding flags for supervision app service. */
    public final int SUPERVISION_APP_SERVICE_BIND_FLAGS;

    private AppBindingConstants(String settings) {
        sourceSettings = settings;

@@ -113,6 +125,14 @@ public class AppBindingConstants {
                    Context.BIND_NOT_VISIBLE | Context.BIND_FOREGROUND_SERVICE);
        }

        boolean supervisionAppServiceEnabled =
                parser.getBoolean(SUPERVISION_APP_SERVICE_ENABLED_KEY, true);

        int supervisionAppServiceBindFlags =
                parser.getInt(
                        SUPERVISION_APP_SERVICE_BIND_FLAGS_KEY,
                        Context.BIND_NOT_VISIBLE | Context.BIND_FOREGROUND_SERVICE);

        long serviceStableConnectionThresholdSec = parser.getLong(
                SERVICE_STABLE_CONNECTION_THRESHOLD_SEC_KEY, TimeUnit.MINUTES.toSeconds(2));

@@ -133,6 +153,8 @@ public class AppBindingConstants {
        SERVICE_STABLE_CONNECTION_THRESHOLD_SEC = serviceStableConnectionThresholdSec;
        SMS_SERVICE_ENABLED = smsServiceEnabled;
        SMS_APP_BIND_FLAGS = smsAppBindFlags;
        SUPERVISION_APP_SERVICE_ENABLED = supervisionAppServiceEnabled;
        SUPERVISION_APP_SERVICE_BIND_FLAGS = supervisionAppServiceBindFlags;
    }

    /**
@@ -173,5 +195,13 @@ public class AppBindingConstants {
        pw.print(prefix);
        pw.print("  SMS_APP_BIND_FLAGS: 0x");
        pw.println(Integer.toHexString(SMS_APP_BIND_FLAGS));

        pw.print(prefix);
        pw.print("  SUPERVISION_APP_SERVICE_ENABLED: ");
        pw.println(SUPERVISION_APP_SERVICE_ENABLED);

        pw.print(prefix);
        pw.print("  SUPERVISION_APP_SERVICE_BIND_FLAGS: 0x");
        pw.println(Integer.toHexString(SUPERVISION_APP_SERVICE_BIND_FLAGS));
    }
}
+5 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server.appbinding;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppGlobals;
import android.app.supervision.flags.Flags;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -49,6 +50,7 @@ import com.android.server.SystemService.TargetUser;
import com.android.server.am.PersistentConnection;
import com.android.server.appbinding.finders.AppServiceFinder;
import com.android.server.appbinding.finders.CarrierMessagingClientServiceFinder;
import com.android.server.appbinding.finders.SupervisionAppServiceFinder;

import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -149,6 +151,9 @@ public class AppBindingService extends Binder {

        mHandler = BackgroundThread.getHandler();
        mApps.add(new CarrierMessagingClientServiceFinder(context, this::onAppChanged, mHandler));
        if (Flags.enableSupervisionAppService()) {
            mApps.add(new SupervisionAppServiceFinder(context, this::onAppChanged, mHandler));
        }

        // Initialize with the default value to make it non-null.
        mConstants = AppBindingConstants.initializeFromString("");
+130 −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 com.android.server.appbinding.finders;

import android.app.role.OnRoleHoldersChangedListener;
import android.app.role.RoleManager;
import android.app.supervision.ISupervisionAppService;
import android.app.supervision.SupervisionAppService;
import android.app.supervision.flags.Flags;
import android.content.Context;
import android.content.pm.ServiceInfo;
import android.os.Handler;
import android.os.IBinder;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Slog;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.internal.os.BackgroundThread;
import com.android.internal.util.CollectionUtils;
import com.android.server.appbinding.AppBindingConstants;

import java.util.function.BiConsumer;

/** Finds the @{link SupervisionAppService} implementation within the supervision app. */
public class SupervisionAppServiceFinder
        extends AppServiceFinder<SupervisionAppService, ISupervisionAppService> {

    private final RoleManager mRoleManager;

    public SupervisionAppServiceFinder(
            Context context,
            BiConsumer<AppServiceFinder, Integer> listener,
            Handler callbackHandler) {
        super(context, listener, callbackHandler);
        mRoleManager = context.getSystemService(RoleManager.class);
    }

    @Override
    protected boolean isEnabled(AppBindingConstants constants) {
        return constants.SUPERVISION_APP_SERVICE_ENABLED && Flags.enableSupervisionAppService();
    }

    @NonNull
    @Override
    public String getAppDescription() {
        return "[Supervision app]";
    }

    @Override
    protected Class<SupervisionAppService> getServiceClass() {
        return SupervisionAppService.class;
    }

    @Override
    public ISupervisionAppService asInterface(IBinder obj) {
        return ISupervisionAppService.Stub.asInterface(obj);
    }

    @Nullable
    @Override
    public String getTargetPackage(int userId) {
        final String ret =
                CollectionUtils.firstOrNull(
                        mRoleManager.getRoleHoldersAsUser(
                                RoleManager.ROLE_SYSTEM_SUPERVISION, UserHandle.of(userId)));

        if (DEBUG) {
            Slog.d(TAG, "getTargetPackage()=" + ret);
        }

        return ret;
    }

    @NonNull
    @Override
    protected String getServiceAction() {
        return SupervisionAppService.ACTION_BIND_SUPERVISION_APP_SERVICE;
    }

    @NonNull
    @Override
    protected String getServicePermission() {
        return "android.permission.BIND_SUPERVISION_APP_SERVICE";
    }

    @Override
    public void startMonitoring() {
        mRoleManager.addOnRoleHoldersChangedListenerAsUser(
                BackgroundThread.getExecutor(), mRoleHolderChangedListener, UserHandle.ALL);
    }

    @Override
    protected String validateService(ServiceInfo service) {
        final String packageName = service.packageName;
        final String process = service.processName;

        if (process == null || TextUtils.equals(packageName, process)) {
            return "Service must not run on the main process";
        }
        return null; // Null means accept this service.
    }

    @Override
    public int getBindFlags(AppBindingConstants constants) {
        return constants.SUPERVISION_APP_SERVICE_BIND_FLAGS;
    }

    private final OnRoleHoldersChangedListener mRoleHolderChangedListener =
            (role, user) -> {
                if (RoleManager.ROLE_SYSTEM_SUPERVISION.equals(role)) {
                    mListener.accept(SupervisionAppServiceFinder.this, user.getIdentifier());
                }
            };
}