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

Commit e82fff28 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Include activities launched on HSU on dumpsys user." into main

parents 93b3a8b6 f6fe73ad
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -452,3 +452,10 @@ flag {
     description: "For user restrictions about adding or editing shared or private Wi-Fi configurations"
     bug: "390240471"
}

flag {
     name: "hsu_allowlist_activities"
     namespace: "multiuser"
     description: "Adds an allowlist mechanism to decide which activities can be launched when the current user is the headless system user"
     bug: "412177078"
}
+45 −4
Original line number Diff line number Diff line
@@ -16,19 +16,22 @@
package com.android.server.pm;

import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.pm.PackageManagerInternal;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.Process;
import android.os.UserHandle;
import android.util.ArraySet;
import android.util.SparseIntArray;

import com.android.server.LocalServices;

import java.io.PrintWriter;

// TODO(b/414326600): rename (and add unit tests) once it's used to log blocked HSU actions
// TODO(b/414326600): rename (and add unit tests) once the final design is ready (notice that it's
// also used to log UI actions on HSU
/**
 * Class used to report deprecated calls.
 */
@@ -36,7 +39,7 @@ final class MultiuserDeprecationReporter {

    private final Handler mHandler;

    // TODO(b/414326600): merge arrays below and/or use the proper proto / structure
    // TODO(b/414326600): merge collections below and/or use the proper proto / structure

    // Key is "absolute" uid  / app id (i.e., stripping out the user id part), value is count.
    @Nullable // Only set on debuggable builds
@@ -46,6 +49,10 @@ final class MultiuserDeprecationReporter {
    @Nullable // Only set on debuggable builds
    private final SparseIntArray mIsMainUserCalls;

    // Activities launched while the current user is the headless system user.
    @Nullable // Only set on debuggable builds
    private final ArraySet<ComponentName> mLaunchedHsuActivities;

    // Set on demand, Should not be used directly (but through getPackageManagerInternal() instead).
    @Nullable
    private PackageManagerInternal mPmInternal;
@@ -55,9 +62,11 @@ final class MultiuserDeprecationReporter {
        if (Build.isDebuggable()) {
            mGetMainUserCalls = new SparseIntArray();
            mIsMainUserCalls = new SparseIntArray();
            mLaunchedHsuActivities = new ArraySet<>();
        } else {
            mGetMainUserCalls = null;
            mIsMainUserCalls = null;
            mLaunchedHsuActivities = null;
        }
    }

@@ -86,6 +95,14 @@ final class MultiuserDeprecationReporter {
        });
    }

    // TODO(b/414326600): add unit tests (once the proper formats are determined).
    void logLaunchedHsuActivity(ComponentName activity) {
        if (mLaunchedHsuActivities == null) {
            return;
        }
        mHandler.post(() -> mLaunchedHsuActivities.add(activity));
    }

    // NOTE: output format might changed, so it should not be used for automated testing purposes
    // (a proto version will be provided when it's ready)
    void dump(PrintWriter pw) {
@@ -93,6 +110,8 @@ final class MultiuserDeprecationReporter {
        dump(pw, "getMainUser", mGetMainUserCalls);
        pw.println();
        dump(pw, "isMainUser", mIsMainUserCalls);
        pw.println();
        dumpLaunchedHsuActivities(pw);
    }

    private void dump(PrintWriter pw, String method, @Nullable SparseIntArray calls) {
@@ -125,6 +144,26 @@ final class MultiuserDeprecationReporter {
        }
    }

    private void dumpLaunchedHsuActivities(PrintWriter pw) {
        if (mLaunchedHsuActivities == null) {
            pw.println("Not logging launched HSU activities");
            return;
        }
        // TODO(b/414326600): should dump in the mHandler thread (as its state is written in that
        // thread), but it would require blocking the caller until it's done
        int size = mLaunchedHsuActivities.size();
        if (size == 0) {
            pw.println("Good News, Everyone!: no activity launched on HSU!");
            return;
        }
        // TODO(b/414326600): for now they're always launched, but once the allowlist mechanism is
        // implemented, it should print the real action
        pw.printf("%d activities launched on HSU:\n", size);
        for (int i = 0; i < size; i++) {
            pw.printf("  %s\n", mLaunchedHsuActivities.valueAt(i).flattenToShortString());
        }
    }

    // TODO(b/414326600): add unit tests
    void reset(PrintWriter pw) {
        // TODO(b/414326600): should reset in the mHandler thread (as its state is written in that
@@ -136,7 +175,9 @@ final class MultiuserDeprecationReporter {
        if (mIsMainUserCalls != null) {
            mIsMainUserCalls.clear();
        }

        if (mLaunchedHsuActivities != null) {
            mLaunchedHsuActivities.clear();
        }
        pw.println("Reset");
    }

+9 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SpecialUsers.CanBeNULL;
import android.annotation.UserIdInt;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.LauncherUserInfo;
import android.content.pm.UserInfo;
@@ -621,6 +622,14 @@ public abstract class UserManagerInternal {
     */
    public abstract @CanBeNULL @UserIdInt int getSupervisingProfileId();

    /** Optimized version of {@link UserManager#isHeadlessSystemUserMode()} */
    public abstract boolean isHeadlessSystemUserMode();

    // TODO(b/414326600): for now it's only logging launched activities, but once the allowlist
    // mechanism is implemented, it should pass some sort of @HsuUiActionResult int result
    /** Logs an activity launched in the headless system user */
    public abstract void logLaunchedHsuActivity(ComponentName activity);

    /**
     * Checks whether to show a notification for sounds (e.g., alarms, timers, etc.) from background
     * users.
+13 −0
Original line number Diff line number Diff line
@@ -82,6 +82,7 @@ import android.app.StatsManager;
import android.app.admin.DevicePolicyEventLogger;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.IIntentReceiver;
import android.content.Intent;
@@ -8088,6 +8089,7 @@ public class UserManagerService extends IUserManager.Stub {
                case "--visibility-mediator":
                    mUserVisibilityMediator.dump(pw, args);
                    return;
                // TODO(b/414326600): use a different arg for HSU SysUI actions
                case "--deprecated-calls":
                    if (args.length > 1 && args[1].equals("reset")) {
                        mDeprecationReporter.reset(pw);
@@ -8916,6 +8918,17 @@ public class UserManagerService extends IUserManager.Stub {
                }
            }
        }

        @Override
        public boolean isHeadlessSystemUserMode() {
            return UserManagerService.this.isHeadlessSystemUserMode();
        }

        @Override
        public void logLaunchedHsuActivity(ComponentName activity) {
            mDeprecationReporter.logLaunchedHsuActivity(activity);
        }

    } // class LocalService

    /**
+14 −0
Original line number Diff line number Diff line
@@ -1905,6 +1905,20 @@ class ActivityStarter {
                transition.setReady(started, false);
            }
        }

        if (android.multiuser.Flags.hsuAllowlistActivities()
                && isStarted && started.mUserId == UserHandle.USER_SYSTEM) {
            // TODO(b/412177078): for now we're just logging activities launched on HSU, but once
            // the allowlist mechanism is in place, we'll need to change this call to log a
            // successful launch, but also log when it's blocked earlier on (probably before the
            // check for voice session on executeRequest(), as voice interaction is not supported
            // on the HSU)
            var umi = mService.getUserManagerInternal();
            if (umi.isHeadlessSystemUserMode()) {
                umi.logLaunchedHsuActivity(started.mActivityComponent);
            }
        }

        return startedActivityRootTask;
    }