Merge "Finish ops started on behalf of a removed package."
diff --git a/api/test-current.txt b/api/test-current.txt
index a2fead2..bc43692 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -93,6 +93,7 @@
     field public static final java.lang.String OPSTR_WRITE_ICC_SMS = "android:write_icc_sms";
     field public static final java.lang.String OPSTR_WRITE_SMS = "android:write_sms";
     field public static final java.lang.String OPSTR_WRITE_WALLPAPER = "android:write_wallpaper";
+    field public static final int OP_RECORD_AUDIO = 27; // 0x1b
     field public static final int OP_SYSTEM_ALERT_WINDOW = 24; // 0x18
   }
 
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 0e126a3..05a9861 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -174,6 +174,7 @@
     /** @hide */
     public static final int OP_CAMERA = 26;
     /** @hide */
+    @TestApi
     public static final int OP_RECORD_AUDIO = 27;
     /** @hide */
     public static final int OP_PLAY_AUDIO = 28;
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 692b12f..53c9ecb 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -232,7 +232,7 @@
         }
     }
 
-    final ArrayMap<IBinder, ClientState> mClients = new ArrayMap<IBinder, ClientState>();
+    final ArrayMap<IBinder, ClientState> mClients = new ArrayMap<>();
 
     public final class ClientState extends Binder implements DeathRecipient {
         final ArrayList<Op> mStartedOps = new ArrayList<>();
@@ -264,7 +264,7 @@
         public void binderDied() {
             synchronized (AppOpsService.this) {
                 for (int i=mStartedOps.size()-1; i>=0; i--) {
-                    finishOperationLocked(mStartedOps.get(i));
+                    finishOperationLocked(mStartedOps.get(i), /*finishNested*/ true);
                 }
                 mClients.remove(mAppToken);
             }
@@ -397,6 +397,27 @@
                 mUidStates.remove(uid);
             }
 
+            // Finish ops other packages started on behalf of the package.
+            final int clientCount = mClients.size();
+            for (int i = 0; i < clientCount; i++) {
+                final ClientState client = mClients.valueAt(i);
+                if (client.mStartedOps == null) {
+                    continue;
+                }
+                final int opCount = client.mStartedOps.size();
+                for (int j = opCount - 1; j >= 0; j--) {
+                    final Op op = client.mStartedOps.get(j);
+                    if (uid == op.uid && packageName.equals(op.packageName)) {
+                        finishOperationLocked(op, /*finishNested*/ true);
+                        client.mStartedOps.remove(j);
+                        if (op.nesting <= 0) {
+                            scheduleOpActiveChangedIfNeededLocked(op.op,
+                                    uid, packageName, false);
+                        }
+                    }
+                }
+            }
+
             if (ops != null) {
                 scheduleFastWriteLocked();
 
@@ -1326,7 +1347,7 @@
                 throw new IllegalStateException("Operation not started: uid" + op.uid
                         + " pkg=" + op.packageName + " op=" + op.op);
             }
-            finishOperationLocked(op);
+            finishOperationLocked(op, /*finishNested*/ false);
             if (op.nesting <= 0) {
                 scheduleOpActiveChangedIfNeededLocked(code, uid, packageName, false);
             }
@@ -1387,9 +1408,9 @@
         return AppOpsManager.permissionToOpCode(permission);
     }
 
-    void finishOperationLocked(Op op) {
-        if (op.nesting <= 1) {
-            if (op.nesting == 1) {
+    void finishOperationLocked(Op op, boolean finishNested) {
+        if (op.nesting <= 1 || finishNested) {
+            if (op.nesting == 1 || finishNested) {
                 op.duration = (int)(System.currentTimeMillis() - op.time);
                 op.time += op.duration;
             } else {