android.os.Process#SYSTEM_UID源码实例Demo

下面列出了android.os.Process#SYSTEM_UID 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。

源代码1 项目: AndroidComponentPlugin   文件: ContextImpl.java
@Override
public int checkPermission(String permission, int pid, int uid) {
    if (permission == null) {
        throw new IllegalArgumentException("permission is null");
    }

    final IActivityManager am = ActivityManager.getService();
    if (am == null) {
        // Well this is super awkward; we somehow don't have an active
        // ActivityManager instance. If we're testing a root or system
        // UID, then they totally have whatever permission this is.
        final int appId = UserHandle.getAppId(uid);
        if (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID) {
            Slog.w(TAG, "Missing ActivityManager; assuming " + uid + " holds " + permission);
            return PackageManager.PERMISSION_GRANTED;
        }
    }

    try {
        return am.checkPermission(permission, pid, uid);
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}
 
public int getState() {
    if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) {
        Slog.w(TAG, "getState(): report OFF for non-active and non system user");
        return BluetoothAdapter.STATE_OFF;
    }

    try {
        mBluetoothLock.readLock().lock();
        if (mBluetooth != null) {
            return mBluetooth.getState();
        }
    } catch (RemoteException e) {
        Slog.e(TAG, "getState()", e);
    } finally {
        mBluetoothLock.readLock().unlock();
    }
    return BluetoothAdapter.STATE_OFF;
}
 
private boolean isThrottlingExemptLocked(Identity identity) {
    if (identity.mUid == Process.SYSTEM_UID) {
        return true;
    }

    if (mBackgroundThrottlePackageWhitelist.contains(identity.mPackageName)) {
        return true;
    }

    for (LocationProviderProxy provider : mProxyProviders) {
        if (identity.mPackageName.equals(provider.getConnectedPackageName())) {
            return true;
        }
    }

    return false;
}
 
源代码4 项目: container   文件: VClientImpl.java
@Override
public IBinder getAppThread() {
    Binder appThread = ActivityThread.getApplicationThread.call(VirtualCore.mainThread());
    return new FakeIdentityBinder(appThread) {
        @Override
        protected int getFakeUid() {
            return Process.SYSTEM_UID;
        }
    };
}
 
源代码5 项目: AndroidComponentPlugin   文件: ContextImpl.java
/**
 * Logs a warning if the system process directly called a method such as
 * {@link #startService(Intent)} instead of {@link #startServiceAsUser(Intent, UserHandle)}.
 * The "AsUser" variants allow us to properly enforce the user's restrictions.
 */
private void warnIfCallingFromSystemProcess() {
    if (Process.myUid() == Process.SYSTEM_UID) {
        Slog.w(TAG, "Calling a method in the system process without a qualified user: "
                + Debug.getCallers(5));
    }
}
 
源代码6 项目: AndroidComponentPlugin   文件: ContextImpl.java
/**
 * Logs a warning if the system process directly called a method such as
 * {@link #startService(Intent)} instead of {@link #startServiceAsUser(Intent, UserHandle)}.
 * The "AsUser" variants allow us to properly enforce the user's restrictions.
 */
private void warnIfCallingFromSystemProcess() {
    if (Process.myUid() == Process.SYSTEM_UID) {
        Slog.w(TAG, "Calling a method in the system process without a qualified user: "
                + Debug.getCallers(5));
    }
}
 
源代码7 项目: android_9.0.0_r45   文件: ZygoteConnection.java
/**
 * uid 1000 (Process.SYSTEM_UID) may specify any uid > 1000 in normal
 * operation. It may also specify any gid and setgroups() list it chooses.
 * In factory test mode, it may specify any UID.
 *
 * @param args non-null; zygote spawner arguments
 * @param peer non-null; peer credentials
 * @throws ZygoteSecurityException
 */
private static void applyUidSecurityPolicy(Arguments args, Credentials peer)
        throws ZygoteSecurityException {

    if (peer.getUid() == Process.SYSTEM_UID) {
        /* In normal operation, SYSTEM_UID can only specify a restricted
         * set of UIDs. In factory test mode, SYSTEM_UID may specify any uid.
         */
        boolean uidRestricted = FactoryTest.getMode() == FactoryTest.FACTORY_TEST_OFF;

        if (uidRestricted && args.uidSpecified && (args.uid < Process.SYSTEM_UID)) {
            throw new ZygoteSecurityException(
                    "System UID may not launch process with UID < "
                    + Process.SYSTEM_UID);
        }
    }

    // If not otherwise specified, uid and gid are inherited from peer
    if (!args.uidSpecified) {
        args.uid = peer.getUid();
        args.uidSpecified = true;
    }
    if (!args.gidSpecified) {
        args.gid = peer.getGid();
        args.gidSpecified = true;
    }
}
 
源代码8 项目: AndroidComponentPlugin   文件: ContextImpl.java
@Override
public int checkPermission(String permission, int pid, int uid) {
    if (permission == null) {
        throw new IllegalArgumentException("permission is null");
    }

    final IActivityManager am = ActivityManager.getService();
    if (am == null) {
        // Well this is super awkward; we somehow don't have an active
        // ActivityManager instance. If we're testing a root or system
        // UID, then they totally have whatever permission this is.
        final int appId = UserHandle.getAppId(uid);
        if (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID) {
            Slog.w(TAG, "Missing ActivityManager; assuming " + uid + " holds " + permission);
            return PackageManager.PERMISSION_GRANTED;
        }
        Slog.w(TAG, "Missing ActivityManager; assuming " + uid + " does not hold "
                + permission);
        return PackageManager.PERMISSION_DENIED;
    }

    try {
        return am.checkPermission(permission, pid, uid);
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}
 
源代码9 项目: android_9.0.0_r45   文件: ContextImpl.java
/**
 * Logs a warning if the system process directly called a method such as
 * {@link #startService(Intent)} instead of {@link #startServiceAsUser(Intent, UserHandle)}.
 * The "AsUser" variants allow us to properly enforce the user's restrictions.
 */
private void warnIfCallingFromSystemProcess() {
    if (Process.myUid() == Process.SYSTEM_UID) {
        Slog.w(TAG, "Calling a method in the system process without a qualified user: "
                + Debug.getCallers(5));
    }
}
 
源代码10 项目: android_9.0.0_r45   文件: Notifier.java
/**
 * Called when a wake lock is changing.
 */
public void onWakeLockChanging(int flags, String tag, String packageName,
        int ownerUid, int ownerPid, WorkSource workSource, String historyTag,
        int newFlags, String newTag, String newPackageName, int newOwnerUid,
        int newOwnerPid, WorkSource newWorkSource, String newHistoryTag) {

    final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
    final int newMonitorType = getBatteryStatsWakeLockMonitorType(newFlags);
    if (workSource != null && newWorkSource != null
            && monitorType >= 0 && newMonitorType >= 0) {
        if (DEBUG) {
            Slog.d(TAG, "onWakeLockChanging: flags=" + newFlags + ", tag=\"" + newTag
                    + "\", packageName=" + newPackageName
                    + ", ownerUid=" + newOwnerUid + ", ownerPid=" + newOwnerPid
                    + ", workSource=" + newWorkSource);
        }

        final boolean unimportantForLogging = newOwnerUid == Process.SYSTEM_UID
                && (newFlags & PowerManager.UNIMPORTANT_FOR_LOGGING) != 0;
        try {
            mBatteryStats.noteChangeWakelockFromSource(workSource, ownerPid, tag, historyTag,
                    monitorType, newWorkSource, newOwnerPid, newTag, newHistoryTag,
                    newMonitorType, unimportantForLogging);
        } catch (RemoteException ex) {
            // Ignore
        }
    } else {
        onWakeLockReleased(flags, tag, packageName, ownerUid, ownerPid, workSource, historyTag);
        onWakeLockAcquired(newFlags, newTag, newPackageName, newOwnerUid, newOwnerPid,
                newWorkSource, newHistoryTag);
    }
}
 
源代码11 项目: TelePlus-Android   文件: MusicBrowserService.java
@Override
public BrowserRoot onGetRoot(String clientPackageName, int clientUid, Bundle rootHints) {
    if (clientPackageName == null || Process.SYSTEM_UID != clientUid && Process.myUid() != clientUid && !clientPackageName.equals("com.google.android.mediasimulator") && !clientPackageName.equals("com.google.android.projection.gearhead")) {
        return null;
    }
    return new BrowserRoot(MEDIA_ID_ROOT, null);
}
 
源代码12 项目: container   文件: IOHook.java
public static int onGetCallingUid(int originUid) {
    int callingPid = Binder.getCallingPid();
    if (callingPid == Process.myPid()) {
        return VClientImpl.get().getBaseVUid();
    }
    if (callingPid == VirtualCore.get().getSystemPid()) {
        return Process.SYSTEM_UID;
    }
    int vuid = VActivityManager.get().getUidByPid(callingPid);
    if (vuid != -1) {
        return VUserHandle.getAppId(vuid);
    }
    VLog.d(TAG, "Unknown uid: " + callingPid);
    return VClientImpl.get().getBaseVUid();
}
 
源代码13 项目: android_9.0.0_r45   文件: ConnectivityManager.java
private void unsupportedStartingFrom(int version) {
    if (Process.myUid() == Process.SYSTEM_UID) {
        // The getApplicationInfo() call we make below is not supported in system context, and
        // we want to allow the system to use these APIs anyway.
        return;
    }

    if (mContext.getApplicationInfo().targetSdkVersion >= version) {
        throw new UnsupportedOperationException(
                "This method is not supported in target SDK version " + version + " and above");
    }
}
 
源代码14 项目: AndroidComponentPlugin   文件: ContextImpl.java
private ContextImpl(@Nullable ContextImpl container, @NonNull ActivityThread mainThread,
        @NonNull LoadedApk packageInfo, @Nullable String splitName,
        @Nullable IBinder activityToken, @Nullable UserHandle user, int flags,
        @Nullable ClassLoader classLoader) {
    mOuterContext = this;

    // If creator didn't specify which storage to use, use the default
    // location for application.
    if ((flags & (Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE
            | Context.CONTEXT_DEVICE_PROTECTED_STORAGE)) == 0) {
        final File dataDir = packageInfo.getDataDirFile();
        if (Objects.equals(dataDir, packageInfo.getCredentialProtectedDataDirFile())) {
            flags |= Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE;
        } else if (Objects.equals(dataDir, packageInfo.getDeviceProtectedDataDirFile())) {
            flags |= Context.CONTEXT_DEVICE_PROTECTED_STORAGE;
        }
    }

    mMainThread = mainThread;
    mActivityToken = activityToken;
    mFlags = flags;

    if (user == null) {
        user = Process.myUserHandle();
    }
    mUser = user;

    mPackageInfo = packageInfo;
    mSplitName = splitName;
    mClassLoader = classLoader;
    mResourcesManager = ResourcesManager.getInstance();

    if (container != null) {
        mBasePackageName = container.mBasePackageName;
        mOpPackageName = container.mOpPackageName;
        setResources(container.mResources);
        mDisplay = container.mDisplay;
    } else {
        mBasePackageName = packageInfo.mPackageName;
        ApplicationInfo ainfo = packageInfo.getApplicationInfo();
        if (ainfo.uid == Process.SYSTEM_UID && ainfo.uid != Process.myUid()) {
            // Special case: system components allow themselves to be loaded in to other
            // processes.  For purposes of app ops, we must then consider the context as
            // belonging to the package of this process, not the system itself, otherwise
            // the package+uid verifications in app ops will fail.
            mOpPackageName = ActivityThread.currentPackageName();
        } else {
            mOpPackageName = mBasePackageName;
        }
    }

    mContentResolver = new ApplicationContentResolver(this, mainThread, user);
}
 
private void revokeRuntimePermission(String permName, String packageName,
        boolean overridePolicy, int callingUid, int userId, PermissionCallback callback) {
    if (!mUserManagerInt.exists(userId)) {
        Log.e(TAG, "No such user:" + userId);
        return;
    }

    mContext.enforceCallingOrSelfPermission(
            android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
            "revokeRuntimePermission");

    enforceCrossUserPermission(Binder.getCallingUid(), userId,
            true,  // requireFullPermission
            true,  // checkShell
            false, // requirePermissionWhenSameUser
            "revokeRuntimePermission");

    final int appId;

    final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
    if (pkg == null || pkg.mExtras == null) {
        throw new IllegalArgumentException("Unknown package: " + packageName);
    }
    if (mPackageManagerInt.filterAppAccess(pkg, Binder.getCallingUid(), userId)) {
        throw new IllegalArgumentException("Unknown package: " + packageName);
    }
    final BasePermission bp = mSettings.getPermissionLocked(permName);
    if (bp == null) {
        throw new IllegalArgumentException("Unknown permission: " + permName);
    }

    bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg);

    // If a permission review is required for legacy apps we represent
    // their permissions as always granted runtime ones since we need
    // to keep the review required permission flag per user while an
    // install permission's state is shared across all users.
    if (mSettings.mPermissionReviewRequired
            && pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M
            && bp.isRuntime()) {
        return;
    }

    final PackageSetting ps = (PackageSetting) pkg.mExtras;
    final PermissionsState permissionsState = ps.getPermissionsState();

    final int flags = permissionsState.getPermissionFlags(permName, userId);
    // Only the system may revoke SYSTEM_FIXED permissions.
    if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0
            && UserHandle.getCallingAppId() != Process.SYSTEM_UID) {
        throw new SecurityException("Non-System UID cannot revoke system fixed permission "
                + permName + " for package " + packageName);
    }
    if (!overridePolicy && (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
        throw new SecurityException("Cannot revoke policy fixed permission "
                + permName + " for package " + packageName);
    }

    if (bp.isDevelopment()) {
        // Development permissions must be handled specially, since they are not
        // normal runtime permissions.  For now they apply to all users.
        if (permissionsState.revokeInstallPermission(bp) !=
                PermissionsState.PERMISSION_OPERATION_FAILURE) {
            if (callback != null) {
                callback.onInstallPermissionRevoked();
            }
        }
        return;
    }

    if (permissionsState.revokeRuntimePermission(bp, userId) ==
            PermissionsState.PERMISSION_OPERATION_FAILURE) {
        return;
    }

    if (bp.isRuntime()) {
        logPermission(MetricsEvent.ACTION_PERMISSION_REVOKED, permName, packageName);
    }

    if (callback != null) {
        final int uid = UserHandle.getUid(userId, pkg.applicationInfo.uid);
        callback.onPermissionRevoked(pkg.applicationInfo.uid, userId);
    }
}
 
源代码16 项目: Jockey   文件: BrowserServicePackageValidator.java
/**
 * @return false if the caller is not authorized to get data from this MediaBrowserService
 */
@SuppressLint("BinaryOperationInTimber")
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
public boolean isCallerAllowed(Context context, String callingPackage, int callingUid) {
    // Always allow calls from the framework, self app or development environment.
    if (Process.SYSTEM_UID == callingUid || Process.myUid() == callingUid) {
        return true;
    }

    if (isPlatformSigned(context, callingPackage)) {
        return true;
    }

    PackageInfo packageInfo = getPackageInfo(context, callingPackage);
    if (packageInfo == null) {
        return false;
    }
    if (packageInfo.signatures.length != 1) {
        Timber.w("Caller does not have exactly one signature certificate!");
        return false;
    }
    String signature = Base64.encodeToString(
            packageInfo.signatures[0].toByteArray(), Base64.NO_WRAP);

    // Test for known signatures:
    ArrayList<CallerInfo> validCallers = mValidCertificates.get(signature);
    if (validCallers == null) {
        Timber.v("Signature for caller %s is not valid: \n%s", callingPackage, signature);
        if (mValidCertificates.isEmpty()) {
            Timber.w("The list of valid certificates is empty. Either your file "
                    + "res/xml/allowed_media_browser_callers.xml is empty or there was an error "
                    + "while reading it. Check previous log messages.");
        }
        return false;
    }

    // Check if the package name is valid for the certificate:
    StringBuilder expectedPackages = new StringBuilder();
    for (CallerInfo info: validCallers) {
        if (callingPackage.equals(info.packageName)) {
            Timber.v("Valid caller: %s package= %s release=%s",
                    info.name, info.packageName, info.release);
            return true;
        }
        expectedPackages.append(info.packageName).append(' ');
    }

    Timber.i("Caller has a valid certificate, but its package doesn't match any "
            + "expected package for the given certificate. Caller's package is " + callingPackage
            + ". Expected packages as defined in res/xml/allowed_media_browser_callers.xml are ("
            + expectedPackages + "). This caller's certificate is: \n" + signature);

    return false;
}
 
private static void enforceSystemUid() {
    final int uid = Binder.getCallingUid();
    if (uid != Process.SYSTEM_UID) {
        throw new SecurityException("Only available to AID_SYSTEM");
    }
}
 
源代码18 项目: PainlessMusicPlayer   文件: PackageValidator.java
/**
 * @return false if the caller is not authorized to get data from this MediaBrowserService
 */
@SuppressLint("PackageManagerGetSignatures")
boolean isCallerAllowed(Context context, String callingPackage, int callingUid) {
    // Always allow calls from the framework, self app or development environment.
    if (Process.SYSTEM_UID == callingUid || Process.myUid() == callingUid) {
        return true;
    }
    final PackageManager packageManager = context.getPackageManager();
    final PackageInfo packageInfo;
    try {
        packageInfo = packageManager
                .getPackageInfo(callingPackage, PackageManager.GET_SIGNATURES);
    } catch (PackageManager.NameNotFoundException e) {
        Log.w(TAG, "Package manager can't find package: " + callingPackage, e);
        return false;
    }
    if (packageInfo.signatures.length != 1) {
        Log.w(TAG, "Caller has more than one signature certificate!");
        return false;
    }
    final String signature = Base64.encodeToString(
            packageInfo.signatures[0].toByteArray(), Base64.NO_WRAP);

    // Test for known signatures:
    final List<CallerInfo> validCallers = mValidCertificates.get(signature);
    if (validCallers == null) {
        if (Log.logVEnabled()) {
            Log.v(TAG, "Signature for caller " + callingPackage + " is not valid: \n"
                    + signature);
        }
        if (mValidCertificates.isEmpty()) {
            Log.w(TAG, "The list of valid certificates is empty. Either your file " +
                    "res/xml/allowed_media_browser_callers.xml is empty or there was an error "
                    + "while reading it. Check previous log messages.");
        }
        return false;
    }

    // Check if the package name is valid for the certificate:
    final StringBuilder expectedPackages = new StringBuilder();
    for (final CallerInfo info : validCallers) {
        if (callingPackage.equals(info.packageName)) {
            if (Log.logVEnabled()) {
                Log.v(TAG, "Valid caller: " + info.name + "  package=" + info.packageName
                        + " release=" + info.release);
            }
            return true;
        }
        expectedPackages.append(info.packageName).append(' ');
    }

    if (Log.logIEnabled()) {
        Log.i(TAG, "Caller has a valid certificate, but its package doesn't match any "
                + "expected package for the given certificate. Caller's package is "
                + callingPackage
                + ". Expected packages as defined in res/xml/allowed_media_browser_callers.xml are ("
                + expectedPackages + "). This caller's certificate is: \n" + signature);
    }

    return false;
}
 
源代码19 项目: android_9.0.0_r45   文件: ContextImpl.java
private ContextImpl(@Nullable ContextImpl container, @NonNull ActivityThread mainThread,
        @NonNull LoadedApk packageInfo, @Nullable String splitName,
        @Nullable IBinder activityToken, @Nullable UserHandle user, int flags,
        @Nullable ClassLoader classLoader) {
    mOuterContext = this;

    // If creator didn't specify which storage to use, use the default
    // location for application.
    if ((flags & (Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE
            | Context.CONTEXT_DEVICE_PROTECTED_STORAGE)) == 0) {
        final File dataDir = packageInfo.getDataDirFile();
        if (Objects.equals(dataDir, packageInfo.getCredentialProtectedDataDirFile())) {
            flags |= Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE;
        } else if (Objects.equals(dataDir, packageInfo.getDeviceProtectedDataDirFile())) {
            flags |= Context.CONTEXT_DEVICE_PROTECTED_STORAGE;
        }
    }

    mMainThread = mainThread;
    mActivityToken = activityToken;
    mFlags = flags;

    if (user == null) {
        user = Process.myUserHandle();
    }
    mUser = user;

    mPackageInfo = packageInfo;
    mSplitName = splitName;
    mClassLoader = classLoader;
    mResourcesManager = ResourcesManager.getInstance();

    if (container != null) {
        mBasePackageName = container.mBasePackageName;
        mOpPackageName = container.mOpPackageName;
        setResources(container.mResources);
        mDisplay = container.mDisplay;
    } else {
        mBasePackageName = packageInfo.mPackageName;
        ApplicationInfo ainfo = packageInfo.getApplicationInfo();
        if (ainfo.uid == Process.SYSTEM_UID && ainfo.uid != Process.myUid()) {
            // Special case: system components allow themselves to be loaded in to other
            // processes.  For purposes of app ops, we must then consider the context as
            // belonging to the package of this process, not the system itself, otherwise
            // the package+uid verifications in app ops will fail.
            mOpPackageName = ActivityThread.currentPackageName();
        } else {
            mOpPackageName = mBasePackageName;
        }
    }

    mContentResolver = new ApplicationContentResolver(this, mainThread);
}
 
private void updatePermissionFlags(String permName, String packageName, int flagMask,
        int flagValues, int callingUid, int userId, PermissionCallback callback) {
    if (!mUserManagerInt.exists(userId)) {
        return;
    }

    enforceGrantRevokeRuntimePermissionPermissions("updatePermissionFlags");

    enforceCrossUserPermission(callingUid, userId,
            true,  // requireFullPermission
            true,  // checkShell
            false, // requirePermissionWhenSameUser
            "updatePermissionFlags");

    // Only the system can change these flags and nothing else.
    if (callingUid != Process.SYSTEM_UID) {
        flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
        flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
        flagMask &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
        flagValues &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
        flagValues &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
    }

    final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
    if (pkg == null || pkg.mExtras == null) {
        throw new IllegalArgumentException("Unknown package: " + packageName);
    }
    if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
        throw new IllegalArgumentException("Unknown package: " + packageName);
    }

    final BasePermission bp;
    synchronized (mLock) {
        bp = mSettings.getPermissionLocked(permName);
    }
    if (bp == null) {
        throw new IllegalArgumentException("Unknown permission: " + permName);
    }

    final PackageSetting ps = (PackageSetting) pkg.mExtras;
    final PermissionsState permissionsState = ps.getPermissionsState();
    final boolean hadState =
            permissionsState.getRuntimePermissionState(permName, userId) != null;
    final boolean permissionUpdated =
            permissionsState.updatePermissionFlags(bp, userId, flagMask, flagValues);
    if (permissionUpdated && callback != null) {
        // Install and runtime permissions are stored in different places,
        // so figure out what permission changed and persist the change.
        if (permissionsState.getInstallPermissionState(permName) != null) {
            callback.onInstallPermissionUpdated();
        } else if (permissionsState.getRuntimePermissionState(permName, userId) != null
                || hadState) {
            callback.onPermissionUpdated(new int[] { userId }, false);
        }
    }
}