App ops: vibration, neighboring cells, dialing, etc.

Improve handling of vibration op, so that apps are
better blamed (there is now a hidden vibrator API that
supplies the app to blame, and the system now uses this
when vibrating on behalf of an app).

Add operation for retrieving neighboring cell information.

Add a new op for calling a phone number.  This required
plumbing information about the launching package name through
the activity manager, which required changing the internal
startActivity class, which required hitting a ton of code that
uses those internal APIs.

Change-Id: I3f8015634fdb296558f07fe654fb8d53e5c94d07
diff --git a/services/java/com/android/server/AppOpsService.java b/services/java/com/android/server/AppOpsService.java
index bf2a5ae..335917e 100644
--- a/services/java/com/android/server/AppOpsService.java
+++ b/services/java/com/android/server/AppOpsService.java
@@ -203,9 +203,9 @@
 
     @Override
     public void setMode(int code, int uid, String packageName, int mode) {
-        uid = handleIncomingUid(uid);
+        verifyIncomingUid(uid);
         synchronized (this) {
-            Op op = getOpLocked(code, uid, packageName, true);
+            Op op = getOpLocked(AppOpsManager.opToSwitch(code), uid, packageName, true);
             if (op != null) {
                 if (op.mode != mode) {
                     op.mode = mode;
@@ -217,9 +217,9 @@
 
     @Override
     public int checkOperation(int code, int uid, String packageName) {
-        uid = handleIncomingUid(uid);
+        verifyIncomingUid(uid);
         synchronized (this) {
-            Op op = getOpLocked(code, uid, packageName, false);
+            Op op = getOpLocked(AppOpsManager.opToSwitch(code), uid, packageName, false);
             if (op == null) {
                 return AppOpsManager.MODE_ALLOWED;
             }
@@ -229,24 +229,27 @@
 
     @Override
     public int noteOperation(int code, int uid, String packageName) {
-        uid = handleIncomingUid(uid);
+        verifyIncomingUid(uid);
         synchronized (this) {
-            Op op = getOpLocked(code, uid, packageName, true);
-            if (op == null) {
+            Ops ops = getOpsLocked(uid, packageName, true);
+            if (ops == null) {
                 if (DEBUG) Log.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
                         + " package " + packageName);
                 return AppOpsManager.MODE_IGNORED;
             }
+            Op op = getOpLocked(ops, code, true);
             if (op.duration == -1) {
                 Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName
                         + " code " + code + " time=" + op.time + " duration=" + op.duration);
             }
             op.duration = 0;
-            if (op.mode != AppOpsManager.MODE_ALLOWED) {
-                if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code " + code
-                        + " uid " + uid + " package " + packageName);
+            final int switchCode = AppOpsManager.opToSwitch(code);
+            final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
+            if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
+                if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code "
+                        + switchCode + " (" + code + ") uid " + uid + " package " + packageName);
                 op.rejectTime = System.currentTimeMillis();
-                return op.mode;
+                return switchOp.mode;
             }
             if (DEBUG) Log.d(TAG, "noteOperation: allowing code " + code + " uid " + uid
                     + " package " + packageName);
@@ -257,19 +260,22 @@
 
     @Override
     public int startOperation(int code, int uid, String packageName) {
-        uid = handleIncomingUid(uid);
+        verifyIncomingUid(uid);
         synchronized (this) {
-            Op op = getOpLocked(code, uid, packageName, true);
-            if (op == null) {
+            Ops ops = getOpsLocked(uid, packageName, true);
+            if (ops == null) {
                 if (DEBUG) Log.d(TAG, "startOperation: no op for code " + code + " uid " + uid
                         + " package " + packageName);
                 return AppOpsManager.MODE_IGNORED;
             }
-            if (op.mode != AppOpsManager.MODE_ALLOWED) {
-                if (DEBUG) Log.d(TAG, "startOperation: reject #" + op.mode + " for code " + code
-                        + " uid " + uid + " package " + packageName);
+            Op op = getOpLocked(ops, code, true);
+            final int switchCode = AppOpsManager.opToSwitch(code);
+            final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
+            if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
+                if (DEBUG) Log.d(TAG, "startOperation: reject #" + op.mode + " for code "
+                        + switchCode + " (" + code + ") uid " + uid + " package " + packageName);
                 op.rejectTime = System.currentTimeMillis();
-                return op.mode;
+                return switchOp.mode;
             }
             if (DEBUG) Log.d(TAG, "startOperation: allowing code " + code + " uid " + uid
                     + " package " + packageName);
@@ -284,7 +290,7 @@
 
     @Override
     public void finishOperation(int code, int uid, String packageName) {
-        uid = handleIncomingUid(uid);
+        verifyIncomingUid(uid);
         synchronized (this) {
             Op op = getOpLocked(code, uid, packageName, true);
             if (op == null) {
@@ -305,16 +311,15 @@
         }
     }
 
-    private int handleIncomingUid(int uid) {
+    private void verifyIncomingUid(int uid) {
         if (uid == Binder.getCallingUid()) {
-            return uid;
+            return;
         }
         if (Binder.getCallingPid() == Process.myPid()) {
-            return uid;
+            return;
         }
         mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
                 Binder.getCallingPid(), Binder.getCallingUid(), null);
-        return uid;
     }
 
     private Ops getOpsLocked(int uid, String packageName, boolean edit) {
@@ -377,6 +382,10 @@
         if (ops == null) {
             return null;
         }
+        return getOpLocked(ops, code, edit);
+    }
+
+    private Op getOpLocked(Ops ops, int code, boolean edit) {
         Op op = ops.get(code);
         if (op == null) {
             if (!edit) {