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

Commit 8974f249 authored by Jason Monk's avatar Jason Monk Committed by Android (Google) Code Review
Browse files

Merge "Notify AppOpsService of UserRestrictions and Owners"

parents 843adbba 62062996
Loading
Loading
Loading
Loading
+65 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package android.app;
import android.Manifest;
import android.os.Binder;
import android.os.IBinder;
import android.os.UserManager;
import android.util.ArrayMap;
import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IAppOpsCallback;
@@ -411,6 +412,58 @@ public class AppOpsManager {
            android.Manifest.permission.PACKAGE_USAGE_STATS,
    };

    /**
     * Specifies whether an Op should be restricted by a user restriction.
     * Each Op should be filled with a restriction string from UserManager or
     * null to specify it is not affected by any user restriction.
     */
    private static String[] sOpRestrictions = new String[] {
            null, //COARSE_LOCATION
            null, //FINE_LOCATION
            null, //GPS
            null, //VIBRATE
            null, //READ_CONTACTS
            null, //WRITE_CONTACTS
            null, //READ_CALL_LOG
            null, //WRITE_CALL_LOG
            null, //READ_CALENDAR
            null, //WRITE_CALENDAR
            null, //WIFI_SCAN
            null, //POST_NOTIFICATION
            null, //NEIGHBORING_CELLS
            null, //CALL_PHONE
            null, //READ_SMS
            null, //WRITE_SMS
            null, //RECEIVE_SMS
            null, //RECEIVE_EMERGECY_SMS
            null, //RECEIVE_MMS
            null, //RECEIVE_WAP_PUSH
            null, //SEND_SMS
            null, //READ_ICC_SMS
            null, //WRITE_ICC_SMS
            null, //WRITE_SETTINGS
            null, //SYSTEM_ALERT_WINDOW
            null, //ACCESS_NOTIFICATIONS
            null, //CAMERA
            null, //RECORD_AUDIO
            null, //PLAY_AUDIO
            null, //READ_CLIPBOARD
            null, //WRITE_CLIPBOARD
            null, //TAKE_MEDIA_BUTTONS
            null, //TAKE_AUDIO_FOCUS
            null, //AUDIO_MASTER_VOLUME
            null, //AUDIO_VOICE_VOLUME
            null, //AUDIO_RING_VOLUME
            null, //AUDIO_MEDIA_VOLUME
            null, //AUDIO_ALARM_VOLUME
            null, //AUDIO_NOTIFICATION_VOLUME
            null, //AUDIO_BLUETOOTH_VOLUME
            null, //WAKE_LOCK
            null, //MONITOR_LOCATION
            null, //MONITOR_HIGH_POWER_LOCATION
            null, //GET_USAGE_STATS
    };

    /**
     * This specifies the default mode for each operation.
     */
@@ -542,6 +595,10 @@ public class AppOpsManager {
            throw new IllegalStateException("sOpDisableReset length " + sOpDisableReset.length
                    + " should be " + _NUM_OP);
        }
        if (sOpRestrictions.length != _NUM_OP) {
            throw new IllegalStateException("sOpRestrictions length " + sOpRestrictions.length
                    + " should be " + _NUM_OP);
        }
        for (int i=0; i<_NUM_OP; i++) {
            if (sOpToString[i] != null) {
                sOpStrToOp.put(sOpToString[i], i);
@@ -574,6 +631,14 @@ public class AppOpsManager {
        return sOpPerms[op];
    }

    /**
     * Retrieve the user restriction associated with an operation, or null if there is not one.
     * @hide
     */
    public static String opToRestriction(int op) {
        return sOpRestrictions[op];
    }

    /**
     * Retrieve the default mode for the operation.
     * @hide
+7 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.internal.app;

import android.app.AppOpsManager;
import android.os.Bundle;
import com.android.internal.app.IAppOpsCallback;

interface IAppOpsService {
@@ -38,4 +39,10 @@ interface IAppOpsService {
    void resetAllModes();
    int checkAudioOperation(int code, int stream, int uid, String packageName);
    void setAudioRestriction(int code, int stream, int uid, int mode, in String[] exceptionPackages);

    void setDeviceOwner(String packageName);
    void setProfileOwner(String packageName, int userHandle);
    void setUserRestrictions(in Bundle restrictions, int userHandle);
    void removeUser(int userHandle);

}
+96 −0
Original line number Diff line number Diff line
@@ -36,12 +36,14 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.media.AudioService;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
@@ -49,6 +51,7 @@ import android.util.Log;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.TimeUtils;
import android.util.Xml;

@@ -56,6 +59,7 @@ import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
import com.google.android.util.AbstractMessageParser.MusicTrack;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -91,6 +95,10 @@ public class AppOpsService extends IAppOpsService.Stub {
    final SparseArray<HashMap<String, Ops>> mUidOps
            = new SparseArray<HashMap<String, Ops>>();

    private int mDeviceOwnerUid;
    private final SparseIntArray mProfileOwnerUids = new SparseIntArray();
    private final SparseArray<boolean[]> mOpRestrictions = new SparseArray<boolean[]>();

    public final static class Ops extends SparseArray<Op> {
        public final String packageName;
        public final int uid;
@@ -548,6 +556,9 @@ public class AppOpsService extends IAppOpsService.Stub {
        verifyIncomingUid(uid);
        verifyIncomingOp(code);
        synchronized (this) {
            if (isOpRestricted(uid, code)) {
                return AppOpsManager.MODE_IGNORED;
            }
            Op op = getOpLocked(AppOpsManager.opToSwitch(code), uid, packageName, false);
            if (op == null) {
                return AppOpsManager.opToDefaultMode(code);
@@ -631,6 +642,9 @@ public class AppOpsService extends IAppOpsService.Stub {
                return AppOpsManager.MODE_ERRORED;
            }
            Op op = getOpLocked(ops, code, true);
            if (isOpRestricted(uid, code)) {
                return AppOpsManager.MODE_IGNORED;
            }
            if (op.duration == -1) {
                Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName
                        + " code " + code + " time=" + op.time + " duration=" + op.duration);
@@ -665,6 +679,9 @@ public class AppOpsService extends IAppOpsService.Stub {
                return AppOpsManager.MODE_ERRORED;
            }
            Op op = getOpLocked(ops, code, true);
            if (isOpRestricted(uid, code)) {
                return AppOpsManager.MODE_IGNORED;
            }
            final int switchCode = AppOpsManager.opToSwitch(code);
            final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
            if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
@@ -830,6 +847,23 @@ public class AppOpsService extends IAppOpsService.Stub {
        return op;
    }

    private boolean isOpRestricted(int uid, int code) {
        int userHandle = UserHandle.getUserId(uid);
        boolean[] opRestrictions = mOpRestrictions.get(userHandle);
        if ((opRestrictions != null) && opRestrictions[code]) {
            if (userHandle == UserHandle.USER_OWNER) {
                if (uid != mDeviceOwnerUid) {
                    return true;
                }
            } else {
                if (uid != mProfileOwnerUids.get(userHandle, -1)) {
                    return true;
                }
            }
        }
        return false;
    }

    void readState() {
        synchronized (mFile) {
            synchronized (this) {
@@ -1167,4 +1201,66 @@ public class AppOpsService extends IAppOpsService.Stub {
        int mode;
        ArraySet<String> exceptionPackages = NO_EXCEPTIONS;
    }

    @Override
    public void setDeviceOwner(String packageName) throws RemoteException {
        checkSystemUid("setDeviceOwner");
        try {
            mDeviceOwnerUid = mContext.getPackageManager().getPackageUid(packageName,
                    UserHandle.USER_OWNER);
        } catch (NameNotFoundException e) {
            Log.e(TAG, "Could not find Device Owner UID");
            mDeviceOwnerUid = -1;
            throw new IllegalArgumentException("Could not find device owner package "
                    + packageName);
        }
    }

    @Override
    public void setProfileOwner(String packageName, int userHandle) throws RemoteException {
        checkSystemUid("setProfileOwner");
        try {
            int uid = mContext.getPackageManager().getPackageUid(packageName,
                    userHandle);
            mProfileOwnerUids.put(userHandle, uid);
        } catch (NameNotFoundException e) {
            Log.e(TAG, "Could not find Profile Owner UID");
            mProfileOwnerUids.put(userHandle, -1);
            throw new IllegalArgumentException("Could not find profile owner package "
                    + packageName);
        }
    }

    @Override
    public void setUserRestrictions(Bundle restrictions, int userHandle) throws RemoteException {
        checkSystemUid("setUserRestrictions");
        boolean[] opRestrictions = mOpRestrictions.get(userHandle);
        if (opRestrictions == null) {
            opRestrictions = new boolean[AppOpsManager._NUM_OP];
            mOpRestrictions.put(userHandle, opRestrictions);
        }
        for (int i = 0; i < opRestrictions.length; ++i) {
            String restriction = AppOpsManager.opToRestriction(i);
            if (restriction != null) {
                opRestrictions[i] = restrictions.getBoolean(restriction, false);
            } else {
                opRestrictions[i] = false;
            }
        }
    }

    @Override
    public void removeUser(int userHandle) throws RemoteException {
        checkSystemUid("removeUser");
        mOpRestrictions.remove(userHandle);
        mProfileOwnerUids.removeAt(mProfileOwnerUids.indexOfKey(userHandle));
    }

    private void checkSystemUid(String function) {
        int uid = Binder.getCallingUid();
        if (uid != Process.SYSTEM_UID) {
            throw new SecurityException(function + " must by called by the system");
        }
    }

}
+26 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import android.os.Handler;
import android.os.IUserManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.AtomicFile;
@@ -50,6 +51,7 @@ import android.util.SparseBooleanArray;
import android.util.TimeUtils;
import android.util.Xml;

import com.android.internal.app.IAppOpsService;
import com.android.internal.content.PackageMonitor;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
@@ -162,6 +164,8 @@ public class UserManagerService extends IUserManager.Stub {
    private int mNextSerialNumber;
    private int mUserVersion = 0;

    private IAppOpsService mAppOpsService;

    private static UserManagerService sInstance;

    public static UserManagerService getInstance() {
@@ -236,6 +240,15 @@ public class UserManagerService extends IUserManager.Stub {
    void systemReady() {
        mUserPackageMonitor.register(mContext, null, UserHandle.ALL, false);
        userForeground(UserHandle.USER_OWNER);
        mAppOpsService = IAppOpsService.Stub.asInterface(
                ServiceManager.getService(Context.APP_OPS_SERVICE));
        for (int i = 0; i < mUserIds.length; ++i) {
            try {
                mAppOpsService.setUserRestrictions(mUserRestrictions.get(mUserIds[i]), mUserIds[i]);
            } catch (RemoteException e) {
                Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions");
            }
        }
    }

    @Override
@@ -482,6 +495,14 @@ public class UserManagerService extends IUserManager.Stub {
        synchronized (mPackagesLock) {
            mUserRestrictions.get(userId).clear();
            mUserRestrictions.get(userId).putAll(restrictions);
            long token = Binder.clearCallingIdentity();
            try {
                mAppOpsService.setUserRestrictions(mUserRestrictions.get(userId), userId);
            } catch (RemoteException e) {
                Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions");
            } finally {
                Binder.restoreCallingIdentity(token);
            }
            writeUserLocked(mUsers.get(userId));
        }
    }
@@ -1116,6 +1137,11 @@ public class UserManagerService extends IUserManager.Stub {
                return false;
            }
            mRemovingUserIds.put(userHandle, true);
            try {
                mAppOpsService.removeUser(userHandle);
            } catch (RemoteException e) {
                Log.w(LOG_TAG, "Unable to notify AppOpsService of removing user", e);
            }
            // Set this to a partially created user, so that the user will be purged
            // on next startup, in case the runtime stops now before stopping and
            // removing the user completely.
+5 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Set;

/**
 * Stores and restores state for the Device and Profile owners. By definition there can be
@@ -137,6 +138,10 @@ public class DeviceOwner {
        return profileOwner != null ? profileOwner.name : null;
    }

    Set<Integer> getProfileOwnerKeys() {
        return mProfileOwners.keySet();
    }

    boolean hasDeviceOwner() {
        return mDeviceOwner != null;
    }
Loading