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

Commit e839d709 authored by Tony Mak's avatar Tony Mak
Browse files

Allow Recents in current user to access APIs in its child profile

At this point, we just need to whitelist Recents for these:
isDeviceLocked
loadTaskDescriptionIcon
getActivityInfo

However, I think in the long run, it may need more than that, so I
modified AMS.handleIncomingUser accordingly. PKMS does not use
handleIncomingUser and hence isRecentsAccessingChildProfiles is
introduced there.

Fix: 71722266

Test: Manual
1. Setup work profile
2. Launch some work and personal apps
3. Swipe up to see the new Recents
3. Can see recent apps are rendered correctly with icons badged
   accordingly.
4. Can switch to the task
5. Can remove task

Change-Id: I56b5f6091c232fc8327e01de472467d630570030
parent 3733b8ed
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -339,4 +339,9 @@ public abstract class ActivityManagerInternal {
     * Returns maximum number of users that can run simultaneously.
     */
    public abstract int getMaxRunningUsers();

    /**
     * Returns is the caller has the same uid as the Recents component
     */
    public abstract boolean isCallerRecents(int callingUid);
}
+20 −14
Original line number Diff line number Diff line
@@ -27,9 +27,9 @@ import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
import static android.Manifest.permission.READ_FRAME_BUFFER;
import static android.Manifest.permission.REMOVE_TASKS;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.app.ActivityManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.ActivityManager.RESIZE_MODE_PRESERVE_WINDOW;
import static android.app.ActivityManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManagerInternal.ASSIST_KEY_CONTENT;
import static android.app.ActivityManagerInternal.ASSIST_KEY_DATA;
@@ -120,6 +120,7 @@ import static android.service.voice.VoiceInteractionSession.SHOW_SOURCE_APPLICAT
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static com.android.internal.util.XmlUtils.readBooleanAttribute;
import static com.android.internal.util.XmlUtils.readIntAttribute;
import static com.android.internal.util.XmlUtils.readLongAttribute;
@@ -198,6 +199,7 @@ import static android.view.WindowManager.TRANSIT_NONE;
import static android.view.WindowManager.TRANSIT_TASK_IN_PLACE;
import static android.view.WindowManager.TRANSIT_TASK_OPEN;
import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
@@ -277,8 +279,8 @@ import android.content.pm.IPackageManager;
import android.content.pm.InstrumentationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManagerInternal;
import android.content.pm.ParceledListSlice;
import android.content.pm.PathPermission;
import android.content.pm.PermissionInfo;
@@ -356,18 +358,18 @@ import android.text.style.SuggestionSpan;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.LongSparseArray;
import android.util.StatsLog;
import android.util.TimingsTraceLog;
import android.util.DebugUtils;
import android.util.EventLog;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.Pair;
import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.StatsLog;
import android.util.TimeUtils;
import android.util.TimingsTraceLog;
import android.util.Xml;
import android.util.proto.ProtoOutputStream;
import android.view.Gravity;
@@ -440,6 +442,12 @@ import com.android.server.utils.PriorityDump;
import com.android.server.vr.VrManagerInternal;
import com.android.server.wm.PinnedStackWindowController;
import com.android.server.wm.WindowManagerService;
import dalvik.system.VMRuntime;
import libcore.io.IoUtils;
import libcore.util.EmptyArray;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
@@ -479,11 +487,6 @@ import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import dalvik.system.VMRuntime;
import libcore.io.IoUtils;
import libcore.util.EmptyArray;
public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
@@ -10404,10 +10407,9 @@ public class ActivityManagerService extends IActivityManager.Stub
    @Override
    public Bitmap getTaskDescriptionIcon(String filePath, int userId) {
        if (userId != UserHandle.getCallingUserId()) {
            enforceCallingPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
                    "getTaskDescriptionIcon");
        }
        userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                userId, false, ALLOW_FULL_ONLY, "getTaskDescriptionIcon", null);
        final File passedIconFile = new File(filePath);
        final File legitIconFile = new File(TaskPersister.getUserImagesDir(userId),
                passedIconFile.getName());
@@ -25149,6 +25151,10 @@ public class ActivityManagerService extends IActivityManager.Stub
        public int getMaxRunningUsers() {
            return mUserController.mMaxRunningUsers;
        }
        public boolean isCallerRecents(int callingUid) {
            return getRecentTasks().isCallerRecents(callingUid);
        }
    }
    /**
+11 −1
Original line number Diff line number Diff line
@@ -1431,7 +1431,13 @@ class UserController implements Handler.Callback {

        if (callingUid != 0 && callingUid != SYSTEM_UID) {
            final boolean allow;
            if (mInjector.checkComponentPermission(INTERACT_ACROSS_USERS_FULL, callingPid,
            if (mInjector.isCallerRecents(callingUid)
                    && callingUserId == getCurrentUserId()
                    && isSameProfileGroup(callingUserId, targetUserId)) {
                // If the caller is Recents and it is running in the current user, we then allow it
                // to access its profiles.
                allow = true;
            } else if (mInjector.checkComponentPermission(INTERACT_ACROSS_USERS_FULL, callingPid,
                    callingUid, -1, true) == PackageManager.PERMISSION_GRANTED) {
                // If the caller has this permission, they always pass go.  And collect $200.
                allow = true;
@@ -2149,5 +2155,9 @@ class UserController implements Handler.Callback {
                mService.mLockTaskController.clearLockedTasks(reason);
            }
        }

        protected boolean isCallerRecents(int callingUid) {
            return mService.getRecentTasks().isCallerRecents(callingUid);
        }
    }
}
+32 −2
Original line number Diff line number Diff line
@@ -119,6 +119,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.app.ResourcesManager;
@@ -993,6 +994,7 @@ public class PackageManagerService extends IPackageManager.Stub
    private List<String> mKeepUninstalledPackages;
    private UserManagerInternal mUserManagerInternal;
    private ActivityManagerInternal mActivityManagerInternal;
    private DeviceIdleController.LocalService mDeviceIdleController;
@@ -4576,6 +4578,14 @@ Slog.e("TODD",
        return mUserManagerInternal;
    }
    private ActivityManagerInternal getActivityManagerInternal() {
        if (mActivityManagerInternal == null) {
            mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
        }
        return mActivityManagerInternal;
    }
    private DeviceIdleController.LocalService getDeviceIdleController() {
        if (mDeviceIdleController == null) {
            mDeviceIdleController =
@@ -4736,8 +4746,12 @@ Slog.e("TODD",
            int filterCallingUid, int userId) {
        if (!sUserManager.exists(userId)) return null;
        flags = updateFlagsForComponent(flags, userId, component);
        if (!isRecentsAccessingChildProfiles(Binder.getCallingUid(), userId)) {
            mPermissionManager.enforceCrossUserPermission(Binder.getCallingUid(), userId,
                    false /* requireFullPermission */, false /* checkShell */, "get activity info");
        }
        synchronized (mPackages) {
            PackageParser.Activity a = mActivities.mActivities.get(component);
@@ -4759,6 +4773,22 @@ Slog.e("TODD",
        return null;
    }
    private boolean isRecentsAccessingChildProfiles(int callingUid, int targetUserId) {
        if (!getActivityManagerInternal().isCallerRecents(callingUid)) {
            return false;
        }
        final long token = Binder.clearCallingIdentity();
        try {
            final int callingUserId = UserHandle.getUserId(callingUid);
            if (ActivityManager.getCurrentUser() != callingUserId) {
                return false;
            }
            return sUserManager.isSameProfileGroup(callingUserId, targetUserId);
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }
    @Override
    public boolean activitySupportsIntent(ComponentName component, Intent intent,
            String resolvedType) {