summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2013-08-02 18:10:10 -0700
committerDianne Hackborn <hackbod@google.com>2013-08-02 19:06:25 -0700
commit607b414d0444067e166fa54d8ea37563f2715ea3 (patch)
tree794a9671518840a260c91135d11b13a6339514ee
parent7925e7cc089251afb2faceb3e81eea436647c572 (diff)
downloadbase-607b414d0444067e166fa54d8ea37563f2715ea3.tar.gz
Add new app ops method to reset all op modes.
Change-Id: I5ee6764de8dc31d812e5a788914ab0099bbef4c0
-rw-r--r--core/java/android/app/AppOpsManager.java8
-rw-r--r--core/java/com/android/internal/app/IAppOpsService.aidl1
-rw-r--r--services/java/com/android/server/AppOpsService.java102
3 files changed, 96 insertions, 15 deletions
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index c9776f17fc9a..4fcb18a84b4f 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -422,6 +422,14 @@ public class AppOpsManager {
}
}
+ /** @hide */
+ public void resetAllModes() {
+ try {
+ mService.resetAllModes();
+ } catch (RemoteException e) {
+ }
+ }
+
public void startWatchingMode(int op, String packageName, final Callback callback) {
synchronized (mModeWatchers) {
IAppOpsCallback cb = mModeWatchers.get(callback);
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index a9da86376153..cfd9cc7cb071 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -33,4 +33,5 @@ interface IAppOpsService {
List<AppOpsManager.PackageOps> getPackagesForOps(in int[] ops);
List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, in int[] ops);
void setMode(int code, int uid, String packageName, int mode);
+ void resetAllModes();
}
diff --git a/services/java/com/android/server/AppOpsService.java b/services/java/com/android/server/AppOpsService.java
index a402642bc0de..20ad63683acd 100644
--- a/services/java/com/android/server/AppOpsService.java
+++ b/services/java/com/android/server/AppOpsService.java
@@ -27,6 +27,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import android.app.AppOpsManager;
import android.content.Context;
@@ -42,6 +43,7 @@ import android.os.ServiceManager;
import android.os.UserHandle;
import android.util.AtomicFile;
import android.util.Log;
+import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
@@ -288,6 +290,24 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}
+ private void pruneOp(Op op, int uid, String packageName) {
+ if (op.time == 0 && op.rejectTime == 0) {
+ Ops ops = getOpsLocked(uid, packageName, false);
+ if (ops != null) {
+ ops.remove(op.op);
+ if (ops.size() <= 0) {
+ HashMap<String, Ops> pkgOps = mUidOps.get(uid);
+ if (pkgOps != null) {
+ pkgOps.remove(ops.packageName);
+ if (pkgOps.size() <= 0) {
+ mUidOps.remove(uid);
+ }
+ }
+ }
+ }
+ }
+ }
+
@Override
public void setMode(int code, int uid, String packageName, int mode) {
verifyIncomingUid(uid);
@@ -316,21 +336,7 @@ public class AppOpsService extends IAppOpsService.Stub {
if (mode == AppOpsManager.MODE_ALLOWED) {
// If going into the default mode, prune this op
// if there is nothing else interesting in it.
- if (op.time == 0 && op.rejectTime == 0) {
- Ops ops = getOpsLocked(uid, packageName, false);
- if (ops != null) {
- ops.remove(op.op);
- if (ops.size() <= 0) {
- HashMap<String, Ops> pkgOps = mUidOps.get(uid);
- if (pkgOps != null) {
- pkgOps.remove(ops.packageName);
- if (pkgOps.size() <= 0) {
- mUidOps.remove(uid);
- }
- }
- }
- }
- }
+ pruneOp(op, uid, packageName);
}
scheduleWriteNowLocked();
}
@@ -346,6 +352,72 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}
+ private static HashMap<Callback, ArrayList<Pair<String, Integer>>> addCallbacks(
+ HashMap<Callback, ArrayList<Pair<String, Integer>>> callbacks,
+ String packageName, int op, ArrayList<Callback> cbs) {
+ if (cbs == null) {
+ return callbacks;
+ }
+ if (callbacks == null) {
+ callbacks = new HashMap<Callback, ArrayList<Pair<String, Integer>>>();
+ }
+ for (int i=0; i<cbs.size(); i++) {
+ Callback cb = cbs.get(i);
+ ArrayList<Pair<String, Integer>> reports = callbacks.get(cb);
+ if (reports == null) {
+ reports = new ArrayList<Pair<String, Integer>>();
+ callbacks.put(cb, reports);
+ }
+ reports.add(new Pair<String, Integer>(packageName, op));
+ }
+ return callbacks;
+ }
+
+ @Override
+ public void resetAllModes() {
+ mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
+ Binder.getCallingPid(), Binder.getCallingUid(), null);
+ HashMap<Callback, ArrayList<Pair<String, Integer>>> callbacks = null;
+ synchronized (this) {
+ boolean changed = false;
+ for (int i=0; i<mUidOps.size(); i++) {
+ HashMap<String, Ops> packages = mUidOps.valueAt(i);
+ for (Map.Entry<String, Ops> ent : packages.entrySet()) {
+ String packageName = ent.getKey();
+ Ops pkgOps = ent.getValue();
+ for (int j=0; j<pkgOps.size(); j++) {
+ Op curOp = pkgOps.valueAt(j);
+ if (curOp.mode != AppOpsManager.MODE_ALLOWED) {
+ curOp.mode = AppOpsManager.MODE_ALLOWED;
+ changed = true;
+ callbacks = addCallbacks(callbacks, packageName, curOp.op,
+ mOpModeWatchers.get(curOp.op));
+ callbacks = addCallbacks(callbacks, packageName, curOp.op,
+ mPackageModeWatchers.get(packageName));
+ pruneOp(curOp, mUidOps.keyAt(i), packageName);
+ }
+ }
+ }
+ }
+ if (changed) {
+ scheduleWriteNowLocked();
+ }
+ }
+ if (callbacks != null) {
+ for (Map.Entry<Callback, ArrayList<Pair<String, Integer>>> ent : callbacks.entrySet()) {
+ Callback cb = ent.getKey();
+ ArrayList<Pair<String, Integer>> reports = ent.getValue();
+ for (int i=0; i<reports.size(); i++) {
+ Pair<String, Integer> rep = reports.get(i);
+ try {
+ cb.mCallback.opChanged(rep.second, rep.first);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+ }
+ }
+
@Override
public void startWatchingMode(int op, String packageName, IAppOpsCallback callback) {
synchronized (this) {