OSDN Git Service

Add new app ops method to reset all op modes.
authorDianne Hackborn <hackbod@google.com>
Sat, 3 Aug 2013 01:10:10 +0000 (18:10 -0700)
committerDianne Hackborn <hackbod@google.com>
Sat, 3 Aug 2013 02:06:25 +0000 (19:06 -0700)
Change-Id: I5ee6764de8dc31d812e5a788914ab0099bbef4c0

core/java/android/app/AppOpsManager.java
core/java/com/android/internal/app/IAppOpsService.aidl
services/java/com/android/server/AppOpsService.java

index c9776f1..4fcb18a 100644 (file)
@@ -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);
index a9da863..cfd9cc7 100644 (file)
@@ -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();
 }
index a402642..20ad636 100644 (file)
@@ -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) {