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

Commit 9cea80cd authored by Svet Ganov's avatar Svet Ganov Committed by Svetoslav Ganov
Browse files

No overlay when permissions shown - framework

bug:26973205

Change-Id: I88395e47649191bb7db6dd8723c49e741ef4f1e4
parent 74351554
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -1264,6 +1264,14 @@ public class AppOpsManager {
        }
    }

    /** @hide */
    public void setUserRestriction(int code, boolean restricted, IBinder token) {
        try {
            mService.setUserRestriction(code, restricted, token, mContext.getUserId());
        } catch (RemoteException e) {
        }
    }

    /** @hide */
    public void setMode(int code, int uid, String packageName, int mode) {
        try {
+2 −1
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ interface IAppOpsService {
    int checkAudioOperation(int code, int usage, int uid, String packageName);
    void setAudioRestriction(int code, int usage, int uid, int mode, in String[] exceptionPackages);

    void setUserRestrictions(in Bundle restrictions, int userHandle);
    void setUserRestrictions(in Bundle restrictions, IBinder token, int userHandle);
    void setUserRestriction(int code, boolean restricted, IBinder token, int userHandle);
    void removeUser(int userHandle);
}
+6 −0
Original line number Diff line number Diff line
@@ -2008,6 +2008,12 @@
    <permission android:name="android.permission.UPDATE_APP_OPS_STATS"
        android:protectionLevel="signature|privileged|installer" />

    <!-- Allows an application to update the user app op restrictions.
         Not for use by third party apps.
         @hide -->
    <permission android:name="android.permission.MANAGE_APP_OPS_RESTRICTIONS"
        android:protectionLevel="signature|installer" />

    <!-- @SystemApi Allows an application to open windows that are for use by parts
         of the system user interface.
         <p>Not for use by third-party applications.
+124 −21
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;

import android.Manifest;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.AppGlobals;
@@ -67,6 +68,7 @@ import com.android.internal.app.IAppOpsCallback;
import com.android.internal.os.Zygote;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;

import libcore.util.EmptyArray;
@@ -103,9 +105,10 @@ public class AppOpsService extends IAppOpsService.Stub {
        }
    };

    final SparseArray<UidState> mUidStates = new SparseArray<>();
    private final SparseArray<UidState> mUidStates = new SparseArray<>();

    private final SparseArray<boolean[]> mOpRestrictions = new SparseArray<boolean[]>();
    /** These are app op restrictions imposed per user from various parties */
    private final ArrayMap<IBinder, SparseArray<boolean[]>> mOpUserRestrictions = new ArrayMap<>();

    private static final class UidState {
        public final int uid;
@@ -1263,8 +1266,11 @@ public class AppOpsService extends IAppOpsService.Stub {

    private boolean isOpRestricted(int uid, int code, String packageName) {
        int userHandle = UserHandle.getUserId(uid);
        boolean[] opRestrictions = mOpRestrictions.get(userHandle);
        if ((opRestrictions != null) && opRestrictions[code]) {
        final int restrictionSetCount = mOpUserRestrictions.size();
        for (int i = 0; i < restrictionSetCount; i++) {
            SparseArray<boolean[]> perUserRestrictions = mOpUserRestrictions.valueAt(i);
            boolean[] opRestrictions = perUserRestrictions.get(userHandle);
            if (opRestrictions != null && opRestrictions[code]) {
                if (AppOpsManager.opAllowSystemBypassRestriction(code)) {
                    synchronized (this) {
                        Ops ops = getOpsLocked(uid, packageName, true);
@@ -1275,6 +1281,7 @@ public class AppOpsService extends IAppOpsService.Stub {
                }
                return true;
            }
        }
        return false;
    }

@@ -2049,27 +2056,123 @@ public class AppOpsService extends IAppOpsService.Stub {
    }

    @Override
    public void setUserRestrictions(Bundle restrictions, int userHandle) throws RemoteException {
    public void setUserRestrictions(Bundle restrictions, IBinder token, int userHandle) {
        checkSystemUid("setUserRestrictions");
        boolean[] opRestrictions = mOpRestrictions.get(userHandle);
        if (opRestrictions == null) {
            opRestrictions = new boolean[AppOpsManager._NUM_OP];
            mOpRestrictions.put(userHandle, opRestrictions);
        }
        Preconditions.checkNotNull(token);
        final boolean[] opRestrictions = getOrCreateUserRestrictionsForToken(token, userHandle);
        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;
            final boolean restricted = restriction != null
                    && restrictions.getBoolean(restriction, false);
            setUserRestrictionNoCheck(i, restricted, token, userHandle);
        }
    }

    @Override
    public void setUserRestriction(int code, boolean restricted, IBinder token, int userHandle) {
        if (Binder.getCallingPid() != Process.myPid()) {
            mContext.enforcePermission(Manifest.permission.MANAGE_APP_OPS_RESTRICTIONS,
                    Binder.getCallingPid(), Binder.getCallingUid(), null);
        }
        if (userHandle != UserHandle.getCallingUserId()) {
            if (mContext.checkCallingOrSelfPermission(Manifest.permission
                    .INTERACT_ACROSS_USERS_FULL) != PackageManager.PERMISSION_GRANTED
                && mContext.checkCallingOrSelfPermission(Manifest.permission
                    .INTERACT_ACROSS_USERS) != PackageManager.PERMISSION_GRANTED) {
                throw new SecurityException("Need INTERACT_ACROSS_USERS_FULL or"
                        + " INTERACT_ACROSS_USERS to interact cross user ");
            }
        }
        verifyIncomingOp(code);
        Preconditions.checkNotNull(token);
        setUserRestrictionNoCheck(code, restricted, token, userHandle);
    }

    private void setUserRestrictionNoCheck(int code, boolean restricted, IBinder token,
            int userHandle) {
        final boolean[] opRestrictions = getOrCreateUserRestrictionsForToken(token, userHandle);
        if (opRestrictions[code] == restricted) {
            return;
        }
        opRestrictions[code] = restricted;
        if (!restricted) {
            pruneUserRestrictionsForToken(token, userHandle);
        }

        final ArrayList<Callback> clonedCallbacks;
        synchronized (this) {
            ArrayList<Callback> callbacks = mOpModeWatchers.get(code);
            if (callbacks == null) {
                return;
            }
            clonedCallbacks = new ArrayList<>(callbacks);
        }

        // There are components watching for mode changes such as window manager
        // and location manager which are in our process. The callbacks in these
        // components may require permissions our remote caller does not have.
        final long identity = Binder.clearCallingIdentity();
        try {
            final int callbackCount = clonedCallbacks.size();
            for (int i = 0; i < callbackCount; i++) {
                Callback callback = clonedCallbacks.get(i);
                try {
                    callback.mCallback.opChanged(code, -1, null);
                } catch (RemoteException e) {
                    Log.w(TAG, "Error dispatching op op change", e);
                }
            }
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public void removeUser(int userHandle) throws RemoteException {
        checkSystemUid("removeUser");
        mOpRestrictions.remove(userHandle);
        final int tokenCount = mOpUserRestrictions.size();
        for (int i = tokenCount - 1; i >= 0; i--) {
            SparseArray<boolean[]> opRestrictions = mOpUserRestrictions.valueAt(i);
            if (opRestrictions != null) {
                opRestrictions.remove(userHandle);
                if (opRestrictions.size() <= 0) {
                    mOpUserRestrictions.removeAt(i);
                }
            }
        }
    }


    private void pruneUserRestrictionsForToken(IBinder token, int userHandle) {
        SparseArray<boolean[]> perTokenRestrictions = mOpUserRestrictions.get(token);
        if (perTokenRestrictions != null) {
            final boolean[] opRestrictions = perTokenRestrictions.get(userHandle);
            if (opRestrictions != null) {
                for (boolean restriction : opRestrictions) {
                    if (restriction) {
                        return;
                    }
                }
                perTokenRestrictions.remove(userHandle);
                if (perTokenRestrictions.size() <= 0) {
                    mOpUserRestrictions.remove(token);
                }
            }
        }
    }

    private boolean[] getOrCreateUserRestrictionsForToken(IBinder token, int userHandle) {
        SparseArray<boolean[]> perTokenRestrictions = mOpUserRestrictions.get(token);
        if (perTokenRestrictions == null) {
            perTokenRestrictions = new SparseArray<>();
            mOpUserRestrictions.put(token, perTokenRestrictions);
        }
        boolean[] opRestrictions = perTokenRestrictions.get(userHandle);
        if (opRestrictions == null) {
            opRestrictions = new boolean[AppOpsManager._NUM_OP];
            perTokenRestrictions.put(userHandle, opRestrictions);
        }
        return opRestrictions;
    }

    private void checkSystemUid(String function) {
+4 −1
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import android.os.Debug;
import android.os.Environment;
import android.os.FileUtils;
import android.os.Handler;
import android.os.IBinder;
import android.os.IUserManager;
import android.os.Message;
import android.os.ParcelFileDescriptor;
@@ -188,6 +189,8 @@ public class UserManagerService extends IUserManager.Stub {
    private final File mUsersDir;
    private final File mUserListFile;

    private static final IBinder mUserRestriconToken = new Binder();

    /**
     * User-related information that is used for persisting to flash. Only UserInfo is
     * directly exposed to other system apps.
@@ -1016,7 +1019,7 @@ public class UserManagerService extends IUserManager.Stub {
        if (mAppOpsService != null) { // We skip it until system-ready.
            final long token = Binder.clearCallingIdentity();
            try {
                mAppOpsService.setUserRestrictions(effective, userId);
                mAppOpsService.setUserRestrictions(effective, mUserRestriconToken, userId);
            } catch (RemoteException e) {
                Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions");
            } finally {
Loading