Merge "Add new method to count how many apps have permissions"

This commit is contained in:
Philip P. Moltmann
2018-12-11 03:14:16 +00:00
committed by Android (Google) Code Review
5 changed files with 139 additions and 32 deletions

View File

@@ -4433,6 +4433,7 @@ package android.permission {
ctor public RuntimePermissionPresenterService();
method public final void attachBaseContext(android.content.Context);
method public final android.os.IBinder onBind(android.content.Intent);
method public abstract int onCountPermissionApps(java.util.List<java.lang.String>, boolean, boolean);
method public abstract java.util.List<android.permission.RuntimePermissionPresentationInfo> onGetAppPermissions(java.lang.String);
method public abstract void onRevokeRuntimePermission(java.lang.String, java.lang.String);
field public static final java.lang.String SERVICE_INTERFACE = "android.permission.RuntimePermissionPresenterService";

View File

@@ -26,4 +26,6 @@ import android.os.RemoteCallback;
oneway interface IRuntimePermissionPresenter {
void getAppPermissions(String packageName, in RemoteCallback callback);
void revokeRuntimePermission(String packageName, String permissionName);
void countPermissionApps(in List<String> permissionNames, boolean countOnlyGranted,
boolean countSystem, in RemoteCallback callback);
}

View File

@@ -16,6 +16,7 @@
package android.permission;
import static com.android.internal.util.Preconditions.checkCollectionElementsNotNull;
import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
@@ -62,16 +63,31 @@ public final class RuntimePermissionPresenter {
"android.permission.RuntimePermissionPresenter.key.result";
/**
* Listener for delivering a result.
* Listener for delivering the result of {@link #getAppPermissions}.
*/
public interface OnResultCallback {
public interface OnGetAppPermissionResultCallback {
/**
* The result for {@link #getAppPermissions(String, OnResultCallback, Handler)}.
* The result for {@link #getAppPermissions(String, OnGetAppPermissionResultCallback,
* Handler)}.
*
* @param permissions The permissions list.
*/
void onGetAppPermissions(@NonNull List<RuntimePermissionPresentationInfo> permissions);
}
/**
* Listener for delivering the result of {@link #countPermissionApps}.
*/
public interface OnCountPermissionAppsResultCallback {
/**
* The result for {@link #countPermissionApps(List, boolean,
* OnCountPermissionAppsResultCallback, Handler)}.
*
* @param numApps The number of apps that have one of the permissions
*/
void onCountPermissionApps(int numApps);
}
private static final Object sLock = new Object();
@GuardedBy("sLock")
@@ -106,7 +122,7 @@ public final class RuntimePermissionPresenter {
* @param handler Handler on which to invoke the callback.
*/
public void getAppPermissions(@NonNull String packageName,
@NonNull OnResultCallback callback, @Nullable Handler handler) {
@NonNull OnGetAppPermissionResultCallback callback, @Nullable Handler handler) {
checkNotNull(packageName);
checkNotNull(callback);
@@ -129,6 +145,25 @@ public final class RuntimePermissionPresenter {
mRemoteService, packageName, permissionName));
}
/**
* Count how many apps have one of a set of permissions.
*
* @param permissionNames The permissions the app might have
* @param countOnlyGranted Count an app only if the permission is granted to the app
* @param countSystem Also count system apps
* @param callback Callback to receive the result
* @param handler Handler on which to invoke the callback
*/
public void countPermissionApps(@NonNull List<String> permissionNames,
boolean countOnlyGranted, boolean countSystem,
@NonNull OnCountPermissionAppsResultCallback callback, @Nullable Handler handler) {
checkCollectionElementsNotNull(permissionNames, "permissionNames");
checkNotNull(callback);
mRemoteService.processMessage(obtainMessage(RemoteService::countPermissionApps,
mRemoteService, permissionNames, countOnlyGranted, countSystem, callback, handler));
}
private static final class RemoteService
extends Handler implements ServiceConnection {
private static final long UNBIND_TIMEOUT_MILLIS = 10000;
@@ -184,7 +219,7 @@ public final class RuntimePermissionPresenter {
}
private void getAppPermissions(@NonNull String packageName,
@NonNull OnResultCallback callback, @Nullable Handler handler) {
@NonNull OnGetAppPermissionResultCallback callback, @Nullable Handler handler) {
final IRuntimePermissionPresenter remoteInstance;
synchronized (mLock) {
remoteInstance = mRemoteInstance;
@@ -241,6 +276,45 @@ public final class RuntimePermissionPresenter {
}
}
private void countPermissionApps(@NonNull List<String> permissionNames,
boolean countOnlyGranted, boolean countSystem,
@NonNull OnCountPermissionAppsResultCallback callback, @Nullable Handler handler) {
final IRuntimePermissionPresenter remoteInstance;
synchronized (mLock) {
remoteInstance = mRemoteInstance;
}
if (remoteInstance == null) {
return;
}
try {
remoteInstance.countPermissionApps(permissionNames, countOnlyGranted, countSystem,
new RemoteCallback(result -> {
final int numApps;
if (result != null) {
numApps = result.getInt(KEY_RESULT);
} else {
numApps = 0;
}
if (handler != null) {
handler.post(() -> callback.onCountPermissionApps(numApps));
} else {
callback.onCountPermissionApps(numApps);
}
}, this));
} catch (RemoteException re) {
Log.e(TAG, "Error counting permission apps", re);
}
scheduleUnbind();
synchronized (mLock) {
scheduleNextMessageIfNeededLocked();
}
}
private void unbind() {
synchronized (mLock) {
if (mBound) {

View File

@@ -16,6 +16,7 @@
package android.permission;
import static com.android.internal.util.Preconditions.checkCollectionElementsNotNull;
import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
@@ -81,6 +82,18 @@ public abstract class RuntimePermissionPresenterService extends Service {
public abstract void onRevokeRuntimePermission(@NonNull String packageName,
@NonNull String permissionName);
/**
* Count how many apps have one of a set of permissions.
*
* @param permissionNames The permissions the app might have
* @param countOnlyGranted Count an app only if the permission is granted to the app
* @param countSystem Also count system apps
*
* @return the number of apps that have one of the permissions
*/
public abstract int onCountPermissionApps(@NonNull List<String> permissionNames,
boolean countOnlyGranted, boolean countSystem);
@Override
public final IBinder onBind(Intent intent) {
return new IRuntimePermissionPresenter.Stub() {
@@ -106,6 +119,19 @@ public abstract class RuntimePermissionPresenterService extends Service {
RuntimePermissionPresenterService.this, packageName,
permissionName));
}
@Override
public void countPermissionApps(List<String> permissionNames, boolean countOnlyGranted,
boolean countSystem, RemoteCallback callback) {
checkCollectionElementsNotNull(permissionNames, "permissionNames");
checkNotNull(callback, "callback");
mHandler.sendMessage(
obtainMessage(
RuntimePermissionPresenterService::countPermissionApps,
RuntimePermissionPresenterService.this, permissionNames,
countOnlyGranted, countSystem, callback));
}
};
}
@@ -119,4 +145,13 @@ public abstract class RuntimePermissionPresenterService extends Service {
callback.sendResult(null);
}
}
private void countPermissionApps(@NonNull List<String> permissionNames,
boolean countOnlyGranted, boolean countSystem, @NonNull RemoteCallback callback) {
int numApps = onCountPermissionApps(permissionNames, countOnlyGranted, countSystem);
Bundle result = new Bundle();
result.putInt(RuntimePermissionPresenter.KEY_RESULT, numApps);
callback.sendResult(result);
}
}

View File

@@ -15,7 +15,6 @@
*/
package com.android.settingslib.applications;
import android.annotation.NonNull;
import android.content.Context;
import android.permission.RuntimePermissionPresentationInfo;
import android.permission.RuntimePermissionPresenter;
@@ -31,37 +30,33 @@ public class PermissionsSummaryHelper {
final PermissionsResultCallback callback) {
final RuntimePermissionPresenter presenter =
RuntimePermissionPresenter.getInstance(context);
presenter.getAppPermissions(pkg, new RuntimePermissionPresenter.OnResultCallback() {
@Override
public void onGetAppPermissions(
@NonNull List<RuntimePermissionPresentationInfo> permissions) {
final int permissionCount = permissions.size();
presenter.getAppPermissions(pkg, permissions -> {
final int permissionCount = permissions.size();
int grantedStandardCount = 0;
int grantedAdditionalCount = 0;
int requestedCount = 0;
List<CharSequence> grantedStandardLabels = new ArrayList<>();
int grantedStandardCount = 0;
int grantedAdditionalCount = 0;
int requestedCount = 0;
List<CharSequence> grantedStandardLabels = new ArrayList<>();
for (int i = 0; i < permissionCount; i++) {
RuntimePermissionPresentationInfo permission = permissions.get(i);
requestedCount++;
if (permission.isGranted()) {
if (permission.isStandard()) {
grantedStandardLabels.add(permission.getLabel());
grantedStandardCount++;
} else {
grantedAdditionalCount++;
}
for (int i = 0; i < permissionCount; i++) {
RuntimePermissionPresentationInfo permission = permissions.get(i);
requestedCount++;
if (permission.isGranted()) {
if (permission.isStandard()) {
grantedStandardLabels.add(permission.getLabel());
grantedStandardCount++;
} else {
grantedAdditionalCount++;
}
}
Collator collator = Collator.getInstance();
collator.setStrength(Collator.PRIMARY);
Collections.sort(grantedStandardLabels, collator);
callback.onPermissionSummaryResult(grantedStandardCount, requestedCount,
grantedAdditionalCount, grantedStandardLabels);
}
Collator collator = Collator.getInstance();
collator.setStrength(Collator.PRIMARY);
Collections.sort(grantedStandardLabels, collator);
callback.onPermissionSummaryResult(grantedStandardCount, requestedCount,
grantedAdditionalCount, grantedStandardLabels);
}, null);
}