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

Commit e5600778 authored by Craig Mautner's avatar Craig Mautner
Browse files

No longer unlock activity manager to test whitelist

In order to check the DevicePolicyManagerService locktask whitelist
the activity manager had to release its lock preserving internal
state. That is undesirable and not scalable now that we need to check
the whitelist at startup for bug 19995702.

This change causes DPMS to update activity manager with the whitelist
whenever it changes so that activity manager can check the whitelist
without releasing the acitivty manager lock.

Change-Id: I3ed6eb5ceae2cd7e7ae3280abd708d5ce43a2851
parent 63473869
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -2450,6 +2450,15 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
            reply.writeNoException();
            return true;
        }

        case UPDATE_LOCK_TASK_PACKAGES_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            int userId = data.readInt();
            String[] packages = data.readStringArray();
            updateLockTaskPackages(userId, packages);
            reply.writeNoException();
            return true;
        }
        }

        return super.onTransact(code, data, reply, flags);
@@ -5682,5 +5691,18 @@ class ActivityManagerProxy implements IActivityManager
        reply.recycle();
    }

    @Override
    public void updateLockTaskPackages(int userId, String[] packages) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeInt(userId);
        data.writeStringArray(packages);
        mRemote.transact(UPDATE_LOCK_TASK_PACKAGES_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
        reply.readException();
        data.recycle();
        reply.recycle();
    }

    private IBinder mRemote;
}
+2 −0
Original line number Diff line number Diff line
@@ -487,6 +487,7 @@ public interface IActivityManager extends IInterface {

    public void setVoiceKeepAwake(IVoiceInteractionSession session, boolean keepAwake)
            throws RemoteException;
    public void updateLockTaskPackages(int userId, String[] packages) throws RemoteException;

    /*
     * Private non-Binder interfaces
@@ -822,4 +823,5 @@ public interface IActivityManager extends IInterface {
    int SET_DUMP_HEAP_DEBUG_LIMIT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+287;
    int DUMP_HEAP_FINISHED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+288;
    int SET_VOICE_KEEP_AWAKE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+289;
    int UPDATE_LOCK_TASK_PACKAGES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+290;
}
+57 −62
Original line number Diff line number Diff line
@@ -41,7 +41,6 @@ import android.app.IActivityContainerCallback;
import android.app.IAppTask;
import android.app.ITaskStackListener;
import android.app.ProfilerInfo;
import android.app.admin.DevicePolicyManager;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManagerInternal;
import android.appwidget.AppWidgetManager;
@@ -436,6 +435,11 @@ public final class ActivityManagerService extends ActivityManagerNative
     */
    ActivityInfo mLastAddedTaskActivity;
    /**
     * List of packages whitelisted by DevicePolicyManager for locktask. Indexed by userId.
     */
    SparseArray<String[]> mLockTaskPackages = new SparseArray<>();
    public class PendingAssistExtras extends Binder implements Runnable {
        public final ActivityRecord activity;
        public final Bundle extras;
@@ -8451,52 +8455,54 @@ public final class ActivityManagerService extends ActivityManagerNative
        }
    }
    private boolean isLockTaskAuthorized(String pkg) {
        final DevicePolicyManager dpm = (DevicePolicyManager)
                mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
        try {
            int uid = mContext.getPackageManager().getPackageUid(pkg,
                    Binder.getCallingUserHandle().getIdentifier());
            return (uid == Binder.getCallingUid()) && dpm != null && dpm.isLockTaskPermitted(pkg);
        } catch (NameNotFoundException e) {
            return false;
    @Override
    public void updateLockTaskPackages(int userId, String[] packages) {
        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
            throw new SecurityException("updateLockTaskPackage called from non-system process");
        }
        synchronized (this) {
            mLockTaskPackages.put(userId, packages);
        }
    }
    void startLockTaskMode(TaskRecord task) {
        final String pkg;
        synchronized (this) {
            pkg = task.intent.getComponent().getPackageName();
    private boolean isLockTaskAuthorizedLocked(String pkg) {
        String[] packages = mLockTaskPackages.get(mCurrentUserId);
        if (packages == null) {
            return false;
        }
        for (int i = packages.length - 1; i >= 0; --i) {
            if (pkg.equals(packages[i])) {
                return true;
            }
        }
        return false;
    }
    void startLockTaskModeLocked(TaskRecord task) {
        final String pkg = task.intent.getComponent().getPackageName();
        // isSystemInitiated is used to distinguish between locked and pinned mode, as pinned mode
        // is initiated by system after the pinning request was shown and locked mode is initiated
        // by an authorized app directly
        boolean isSystemInitiated = Binder.getCallingUid() == Process.SYSTEM_UID;
        if (!isSystemInitiated && !isLockTaskAuthorized(pkg)) {
            StatusBarManagerInternal statusBarManager = LocalServices.getService(
                    StatusBarManagerInternal.class);
        long ident = Binder.clearCallingIdentity();
        try {
            if (!isSystemInitiated && !isLockTaskAuthorizedLocked(pkg)) {
                StatusBarManagerInternal statusBarManager =
                        LocalServices.getService(StatusBarManagerInternal.class);
                if (statusBarManager != null) {
                    statusBarManager.showScreenPinningRequest();
                }
                return;
            }
        long ident = Binder.clearCallingIdentity();
        try {
            synchronized (this) {
                // Since we lost lock on task, make sure it is still there.
                task = mStackSupervisor.anyTaskForIdLocked(task.taskId);
                if (task != null) {
                    if (!isSystemInitiated
                            && ((mStackSupervisor.getFocusedStack() == null)
                                    || (task != mStackSupervisor.getFocusedStack().topTask()))) {
            final ActivityStack stack = mStackSupervisor.getFocusedStack();
            if (!isSystemInitiated && (stack == null || task != stack.topTask())) {
                throw new IllegalArgumentException("Invalid task, not in foreground");
            }
            mStackSupervisor.setLockTaskModeLocked(task, isSystemInitiated ?
                    ActivityManager.LOCK_TASK_MODE_PINNED :
                    ActivityManager.LOCK_TASK_MODE_LOCKED,
                    "startLockTask");
                }
            }
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
@@ -8504,37 +8510,25 @@ public final class ActivityManagerService extends ActivityManagerNative
    @Override
    public void startLockTaskMode(int taskId) {
        final TaskRecord task;
        long ident = Binder.clearCallingIdentity();
        try {
        synchronized (this) {
                task = mStackSupervisor.anyTaskForIdLocked(taskId);
            }
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
            final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
            if (task != null) {
            startLockTaskMode(task);
                startLockTaskModeLocked(task);
            }
        }
    }
    @Override
    public void startLockTaskMode(IBinder token) {
        final TaskRecord task;
        long ident = Binder.clearCallingIdentity();
        try {
        synchronized (this) {
            final ActivityRecord r = ActivityRecord.forTokenLocked(token);
            if (r == null) {
                return;
            }
                task = r.task;
            }
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
            final TaskRecord task = r.task;
            if (task != null) {
            startLockTaskMode(task);
                startLockTaskModeLocked(task);
            }
        }
    }
@@ -8544,11 +8538,12 @@ public final class ActivityManagerService extends ActivityManagerNative
                "startLockTaskModeOnCurrent");
        long ident = Binder.clearCallingIdentity();
        try {
            ActivityRecord r = null;
            synchronized (this) {
                r = mStackSupervisor.topRunningActivityLocked();
                ActivityRecord r = mStackSupervisor.topRunningActivityLocked();
                if (r != null) {
                    startLockTaskModeLocked(r.task);
                }
            }
            startLockTaskMode(r.task);
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
+16 −8
Original line number Diff line number Diff line
@@ -280,15 +280,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        long mLastMaximumTimeToLock = -1;
        boolean mUserSetupComplete = false;

        final HashMap<ComponentName, ActiveAdmin> mAdminMap
                = new HashMap<ComponentName, ActiveAdmin>();
        final ArrayList<ActiveAdmin> mAdminList
                = new ArrayList<ActiveAdmin>();
        final ArrayList<ComponentName> mRemovingAdmins
                = new ArrayList<ComponentName>();
        final HashMap<ComponentName, ActiveAdmin> mAdminMap = new HashMap<>();
        final ArrayList<ActiveAdmin> mAdminList = new ArrayList<>();
        final ArrayList<ComponentName> mRemovingAdmins = new ArrayList<>();

        // This is the list of component allowed to start lock task mode.
        final List<String> mLockTaskPackages = new ArrayList<String>();
        final List<String> mLockTaskPackages = new ArrayList<>();

        ComponentName mRestrictionsProvider;

@@ -299,7 +296,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
    }

    final SparseArray<DevicePolicyData> mUserData = new SparseArray<DevicePolicyData>();
    final SparseArray<DevicePolicyData> mUserData = new SparseArray<>();

    Handler mHandler = new Handler();

@@ -1596,6 +1593,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        validatePasswordOwnerLocked(policy);
        syncDeviceCapabilitiesLocked(policy);
        updateMaximumTimeToLockLocked(policy);
        updateLockTaskPackagesLocked(policy, userHandle);
    }

    private void updateLockTaskPackagesLocked(DevicePolicyData policy, int userId) {
        IActivityManager am = ActivityManagerNative.getDefault();
        try {
            am.updateLockTaskPackages(userId, policy.mLockTaskPackages.toArray(new String[0]));
        } catch (RemoteException e) {
            // Not gonna happen.
        }
    }

    static void validateQualityConstant(int quality) {
@@ -5515,6 +5522,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {

            // Store the settings persistently.
            saveSettingsLocked(userHandle);
            updateLockTaskPackagesLocked(policy, userHandle);
        }
    }