Test that op-active-listener gets multiple start-finish events

Bug: 145005238
Test: atest AppOpsTest
Change-Id: I1283b235097e476618b3d90f2f4dc3d11bece0b8
diff --git a/tests/tests/appop/src/android/app/appops/cts/AppOpsTest.kt b/tests/tests/appop/src/android/app/appops/cts/AppOpsTest.kt
index 4fc2660..7f05dcf 100644
--- a/tests/tests/appop/src/android/app/appops/cts/AppOpsTest.kt
+++ b/tests/tests/appop/src/android/app/appops/cts/AppOpsTest.kt
@@ -27,6 +27,7 @@
 import android.app.AppOpsManager.MODE_DEFAULT
 import android.app.AppOpsManager.MODE_ERRORED
 import android.app.AppOpsManager.MODE_IGNORED
+import android.app.AppOpsManager.OPSTR_CAMERA
 import android.app.AppOpsManager.OPSTR_READ_CALENDAR
 import android.app.AppOpsManager.OPSTR_RECORD_AUDIO
 import android.app.AppOpsManager.OPSTR_WRITE_CALENDAR
@@ -54,6 +55,7 @@
 import java.util.HashSet
 import java.util.concurrent.CompletableFuture
 import java.util.concurrent.Executor
+import java.util.concurrent.LinkedBlockingDeque
 import java.util.concurrent.TimeUnit
 
 @RunWith(AndroidJUnit4::class)
@@ -275,6 +277,37 @@
     }
 
     @Test
+    fun startOpTwiceAndVerifyChangeListener() {
+        runWithShellPermissionIdentity {
+            val receivedActiveState = LinkedBlockingDeque<Boolean>()
+            val activeWatcher =
+                    AppOpsManager.OnOpActiveChangedListener { _, _, packageName, active ->
+                        if (packageName == mOpPackageName) {
+                            receivedActiveState.push(active)
+                        }
+                    }
+
+            mAppOps.startWatchingActive(arrayOf(OPSTR_CAMERA), Executor { it.run() },
+                    activeWatcher)
+            try {
+                mAppOps.startOp(OPSTR_CAMERA, mMyUid, mOpPackageName, null, null)
+                assertTrue(receivedActiveState.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)!!)
+
+                mAppOps.finishOp(OPSTR_CAMERA, mMyUid, mOpPackageName, null)
+                assertFalse(receivedActiveState.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)!!)
+
+                mAppOps.startOp(OPSTR_CAMERA, mMyUid, mOpPackageName, null, null)
+                assertTrue(receivedActiveState.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)!!)
+
+                mAppOps.finishOp(OPSTR_CAMERA, mMyUid, mOpPackageName, null)
+                assertFalse(receivedActiveState.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)!!)
+            } finally {
+                mAppOps.stopWatchingActive(activeWatcher)
+            }
+        }
+    }
+
+    @Test
     fun finishOpWithoutStartOp() {
         assertFalse(mAppOps.isOpActive(OPSTR_FINE_LOCATION, mMyUid, mOpPackageName))