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

Commit 3b5de448 authored by Nikita Ioffe's avatar Nikita Ioffe Committed by Android (Google) Code Review
Browse files

Merge changes from topics "presubmit-am-1dec1aa04236490e8d2a03998a4272b7",...

Merge changes from topics "presubmit-am-1dec1aa04236490e8d2a03998a4272b7", "sdk-sandbox-instr" into tm-dev

* changes:
  Add a way to instrument sdk sandbox processes
  Sdk Sandbox should be able to see it's client app
parents 4bd32142 99ba880e
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -191,6 +191,8 @@ public class Am extends BaseCommand {
                instrument.noRestart = true;
            } else if (opt.equals("--always-check-signature")) {
                instrument.alwaysCheckSignature = true;
            } else if (opt.equals("--instrument-sdk-sandbox")) {
                instrument.instrumentSdkSandbox = true;
            } else {
                System.err.println("Error: Unknown option: " + opt);
                return;
+5 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.app.ActivityManager.INSTR_FLAG_ALWAYS_CHECK_SIGNATURE;
import static android.app.ActivityManager.INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS;
import static android.app.ActivityManager.INSTR_FLAG_DISABLE_ISOLATED_STORAGE;
import static android.app.ActivityManager.INSTR_FLAG_DISABLE_TEST_API_CHECKS;
import static android.app.ActivityManager.INSTR_FLAG_INSTRUMENT_SDK_SANDBOX;
import static android.app.ActivityManager.INSTR_FLAG_NO_RESTART;

import android.app.IActivityManager;
@@ -97,6 +98,7 @@ public class Instrument {
    // Required
    public String componentNameArg;
    public boolean alwaysCheckSignature = false;
    public boolean instrumentSdkSandbox = false;

    /**
     * Construct the instrument command runner.
@@ -524,6 +526,9 @@ public class Instrument {
            if (alwaysCheckSignature) {
                flags |= INSTR_FLAG_ALWAYS_CHECK_SIGNATURE;
            }
            if (instrumentSdkSandbox) {
                flags |= INSTR_FLAG_INSTRUMENT_SDK_SANDBOX;
            }
            if (!mAm.startInstrumentation(cn, profileFile, flags, args, watcher, connection, userId,
                        abi)) {
                throw new AndroidException("INSTRUMENTATION_FAILED: " + cn.flattenToString());
+5 −0
Original line number Diff line number Diff line
@@ -186,6 +186,11 @@ public class ActivityManager {
     * @hide
     */
    public static final int INSTR_FLAG_ALWAYS_CHECK_SIGNATURE = 1 << 4;
    /**
     * Instrument Sdk Sandbox process that corresponds to the target package.
     * @hide
     */
    public static final int INSTR_FLAG_INSTRUMENT_SDK_SANDBOX = 1 << 5;

    static final class UidObserver extends IUidObserver.Stub {
        final OnUidImportanceListener mListener;
+186 −20
Original line number Diff line number Diff line
@@ -406,6 +406,7 @@ import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.pm.pkg.SELinuxUtil;
import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
import com.android.server.pm.snapshot.PackageDataSnapshot;
import com.android.server.sdksandbox.SdkSandboxManagerLocal;
import com.android.server.uri.GrantUri;
import com.android.server.uri.NeededUriGrants;
import com.android.server.uri.UriGrantsManagerInternal;
@@ -6584,6 +6585,30 @@ public class ActivityManagerService extends IActivityManager.Stub
    final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
            boolean disableHiddenApiChecks, boolean disableTestApiChecks,
            String abiOverride, int zygotePolicyFlags) {
        return addAppLocked(
                info,
                customProcess,
                isolated,
                /* isSdkSandbox= */ false,
                /* sdkSandboxUid= */ 0,
                /* sdkSandboxClientAppPackage= */ null,
                disableHiddenApiChecks,
                disableTestApiChecks,
                abiOverride,
                zygotePolicyFlags);
    }
    final ProcessRecord addAppLocked(
            ApplicationInfo info,
            String customProcess,
            boolean isolated,
            boolean isSdkSandbox,
            int sdkSandboxUid,
            @Nullable String sdkSandboxClientAppPackage,
            boolean disableHiddenApiChecks,
            boolean disableTestApiChecks,
            String abiOverride,
            int zygotePolicyFlags) {
        ProcessRecord app;
        if (!isolated) {
            app = getProcessRecordLocked(customProcess != null ? customProcess : info.processName,
@@ -6593,8 +6618,14 @@ public class ActivityManagerService extends IActivityManager.Stub
        }
        if (app == null) {
            app = mProcessList.newProcessRecordLocked(info, customProcess, isolated, 0,
                    false, 0, null,
            app = mProcessList.newProcessRecordLocked(
                    info,
                    customProcess,
                    isolated,
                    /* isolatedUid= */0,
                    isSdkSandbox,
                    sdkSandboxUid,
                    sdkSandboxClientAppPackage,
                    new HostingRecord("added application",
                            customProcess != null ? customProcess : info.processName));
            updateLruProcessLocked(app, false, null);
@@ -6606,6 +6637,8 @@ public class ActivityManagerService extends IActivityManager.Stub
                Event.APP_COMPONENT_USED);
        // This package really, really can not be stopped.
        // TODO: how set package stopped state should work for sdk sandboxes?
        if (!isSdkSandbox) {
            try {
                AppGlobals.getPackageManager().setPackageStoppedState(
                        info.packageName, false, UserHandle.getUserId(app.uid));
@@ -6614,6 +6647,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                Slog.w(TAG, "Failed trying to unstop package "
                        + info.packageName + ": " + e);
            }
        }
        if ((info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
            app.setPersistent(true);
@@ -14437,6 +14471,32 @@ public class ActivityManagerService extends IActivityManager.Stub
                }
            }
            boolean disableHiddenApiChecks = ai.usesNonSdkApi()
                    || (flags & INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS) != 0;
            boolean disableTestApiChecks = disableHiddenApiChecks
                    || (flags & INSTR_FLAG_DISABLE_TEST_API_CHECKS) != 0;
            if (disableHiddenApiChecks || disableTestApiChecks) {
                enforceCallingPermission(android.Manifest.permission.DISABLE_HIDDEN_API_CHECKS,
                        "disable hidden API checks");
            }
            if ((flags & ActivityManager.INSTR_FLAG_INSTRUMENT_SDK_SANDBOX) != 0) {
                return startInstrumentationOfSdkSandbox(
                        className,
                        profileFile,
                        arguments,
                        watcher,
                        uiAutomationConnection,
                        userId,
                        abiOverride,
                        ii,
                        ai,
                        noRestart,
                        disableHiddenApiChecks,
                        disableTestApiChecks);
            }
            ActiveInstrumentation activeInstr = new ActiveInstrumentation(this);
            activeInstr.mClass = className;
            String defProcess = ai.processName;;
@@ -14461,15 +14521,6 @@ public class ActivityManagerService extends IActivityManager.Stub
                    START_FOREGROUND_SERVICES_FROM_BACKGROUND, callingPid, callingUid)
                            == PackageManager.PERMISSION_GRANTED;
            activeInstr.mNoRestart = noRestart;
            boolean disableHiddenApiChecks = ai.usesNonSdkApi()
                    || (flags & INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS) != 0;
            boolean disableTestApiChecks = disableHiddenApiChecks
                    || (flags & INSTR_FLAG_DISABLE_TEST_API_CHECKS) != 0;
            if (disableHiddenApiChecks || disableTestApiChecks) {
                enforceCallingPermission(android.Manifest.permission.DISABLE_HIDDEN_API_CHECKS,
                        "disable hidden API checks");
            }
            final long origId = Binder.clearCallingIdentity();
@@ -14515,6 +14566,111 @@ public class ActivityManagerService extends IActivityManager.Stub
        return true;
    }
    @GuardedBy("this")
    private boolean startInstrumentationOfSdkSandbox(
            ComponentName className,
            String profileFile,
            Bundle arguments,
            IInstrumentationWatcher watcher,
            IUiAutomationConnection uiAutomationConnection,
            int userId,
            String abiOverride,
            InstrumentationInfo instrumentationInfo,
            ApplicationInfo sdkSandboxClientAppInfo,
            boolean noRestart,
            boolean disableHiddenApiChecks,
            boolean disableTestApiChecks) {
        if (noRestart) {
            reportStartInstrumentationFailureLocked(
                    watcher,
                    className,
                    "Instrumenting sdk sandbox with --no-restart flag is not supported");
            return false;
        }
        final ApplicationInfo sdkSandboxInfo;
        try {
            final PackageManager pm = mContext.getPackageManager();
            sdkSandboxInfo = pm.getApplicationInfoAsUser(pm.getSdkSandboxPackageName(), 0, userId);
        } catch (NameNotFoundException e) {
            reportStartInstrumentationFailureLocked(
                    watcher, className, "Can't find SdkSandbox package");
            return false;
        }
        final SdkSandboxManagerLocal sandboxManagerLocal =
                LocalManagerRegistry.getManager(SdkSandboxManagerLocal.class);
        if (sandboxManagerLocal == null) {
            reportStartInstrumentationFailureLocked(
                    watcher, className, "Can't locate SdkSandboxManagerLocal");
            return false;
        }
        final String processName = sandboxManagerLocal.getSdkSandboxProcessNameForInstrumentation(
                sdkSandboxClientAppInfo);
        ActiveInstrumentation activeInstr = new ActiveInstrumentation(this);
        activeInstr.mClass = className;
        activeInstr.mTargetProcesses = new String[]{processName};
        activeInstr.mTargetInfo = sdkSandboxInfo;
        activeInstr.mProfileFile = profileFile;
        activeInstr.mArguments = arguments;
        activeInstr.mWatcher = watcher;
        activeInstr.mUiAutomationConnection = uiAutomationConnection;
        activeInstr.mResultClass = className;
        activeInstr.mHasBackgroundActivityStartsPermission = false;
        activeInstr.mHasBackgroundForegroundServiceStartsPermission = false;
        // Instrumenting sdk sandbox without a restart is not supported
        activeInstr.mNoRestart = false;
        final int callingUid = Binder.getCallingUid();
        final long token = Binder.clearCallingIdentity();
        try {
            sandboxManagerLocal.notifyInstrumentationStarted(
                    sdkSandboxClientAppInfo.packageName, sdkSandboxClientAppInfo.uid);
            synchronized (mProcLock) {
                int sdkSandboxUid = Process.toSdkSandboxUid(sdkSandboxClientAppInfo.uid);
                // Kill the package sdk sandbox process belong to. At this point sdk sandbox is
                // already killed.
                forceStopPackageLocked(
                        instrumentationInfo.targetPackage,
                        /* appId= */ -1,
                        /* callerWillRestart= */ true,
                        /* purgeCache= */ false,
                        /* doIt= */ true,
                        /* evenPersistent= */ true,
                        /* uninstalling= */ false,
                        userId,
                        "start instr");
                ProcessRecord app = addAppLocked(
                        sdkSandboxInfo,
                        processName,
                        /* isolated= */ false,
                        /* isSdkSandbox= */ true,
                        sdkSandboxUid,
                        sdkSandboxClientAppInfo.packageName,
                        disableHiddenApiChecks,
                        disableTestApiChecks,
                        abiOverride,
                        ZYGOTE_POLICY_FLAG_EMPTY);
                app.setActiveInstrumentation(activeInstr);
                activeInstr.mFinished = false;
                activeInstr.mSourceUid = callingUid;
                activeInstr.mRunningProcesses.add(app);
                if (!mActiveInstrumentation.contains(activeInstr)) {
                    mActiveInstrumentation.add(activeInstr);
                }
            }
        } finally {
            Binder.restoreCallingIdentity(token);
        }
        return true;
    }
    private void instrumentWithoutRestart(ActiveInstrumentation activeInstr,
            ApplicationInfo targetInfo) {
        ProcessRecord pr;
@@ -14637,7 +14793,17 @@ public class ActivityManagerService extends IActivityManager.Stub
            app.setActiveInstrumentation(null);
        }
        if (!instr.mNoRestart) {
        if (app.isSdkSandbox) {
            // For sharedUid apps this will kill all sdk sandbox processes, which is not ideal.
            // TODO(b/209061624): should we call ProcessList.removeProcessLocked instead?
            killUid(UserHandle.getAppId(app.uid), UserHandle.getUserId(app.uid), "finished instr");
            final SdkSandboxManagerLocal sandboxManagerLocal =
                    LocalManagerRegistry.getManager(SdkSandboxManagerLocal.class);
            if (sandboxManagerLocal != null) {
                sandboxManagerLocal.notifyInstrumentationFinished(
                        app.sdkSandboxClientAppPackage, Process.getAppUidForSdkSandboxUid(app.uid));
            }
        } else if (!instr.mNoRestart) {
            forceStopPackageLocked(app.info.packageName, -1, false, false, true, true, false,
                    app.userId,
                    "finished inst");
+7 −2
Original line number Diff line number Diff line
@@ -129,8 +129,6 @@ import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.pm.pkg.PackageState;
import com.android.server.pm.pkg.PackageStateImpl;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.PackageStateUtils;
import com.android.server.pm.pkg.PackageUserStateInternal;
@@ -2638,6 +2636,13 @@ public class ComputerEngine implements Computer {
    public final boolean shouldFilterApplication(@Nullable PackageStateInternal ps,
            int callingUid, @Nullable ComponentName component,
            @PackageManager.ComponentType int componentType, int userId) {
        if (Process.isSdkSandboxUid(callingUid)) {
            int clientAppUid = Process.getAppUidForSdkSandboxUid(callingUid);
            // SDK sandbox should be able to see it's client app
            if (clientAppUid == UserHandle.getUid(userId, ps.getAppId())) {
                return false;
            }
        }
        // if we're in an isolated process, get the real calling UID
        if (Process.isIsolated(callingUid)) {
            callingUid = getIsolatedOwner(callingUid);