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

Commit ecd3ac4e authored by Cintia Martins's avatar Cintia Martins Committed by Android (Google) Code Review
Browse files

Merge "SupervisionAppService Binding." into main

parents b7976007 fb643f64
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -111,7 +111,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",
@@ -125,6 +124,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",
@@ -873,9 +873,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",
    ],
}

@@ -1443,6 +1443,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());
                }
            };
}