Calling opChanged on package suspend / unsuspend

checkAudioOperation returned MODE_IGNORED when a package was suspended,
but any AppOpsWatcher registered for audio operation did not callback
when a package got suspended. This lead to inconsistent state for
services that were watching for app op changes.

Test: atest FrameworksServicesTests:SuspendPackagesTest

Bug: 112486945
Bug: 110077884
Change-Id: Ibfc378dd4ea8dd38ef002c1ac668c479afa8fd47
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index cd98263..dedb237 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -16,6 +16,7 @@
 
 package com.android.server;
 
+import static android.app.AppOpsManager.OP_PLAY_AUDIO;
 import static android.app.AppOpsManager.UID_STATE_BACKGROUND;
 import static android.app.AppOpsManager.UID_STATE_CACHED;
 import static android.app.AppOpsManager.UID_STATE_FOREGROUND;
@@ -36,8 +37,11 @@
 import android.app.AppOpsManager.HistoricalPackageOps;
 import android.app.AppOpsManagerInternal;
 import android.app.AppOpsManagerInternal.CheckOpsDelegate;
+import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
@@ -645,6 +649,26 @@
             }
         }
 
+        final IntentFilter packageSuspendFilter = new IntentFilter();
+        packageSuspendFilter.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED);
+        packageSuspendFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
+        mContext.registerReceiver(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                final int[] changedUids = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
+                final String[] changedPkgs = intent.getStringArrayExtra(
+                        Intent.EXTRA_CHANGED_PACKAGE_LIST);
+                final ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(OP_PLAY_AUDIO);
+                for (int i = 0; i < changedUids.length; i++) {
+                    final int changedUid = changedUids[i];
+                    final String changedPkg = changedPkgs[i];
+                    // We trust packagemanager to insert matching uid and packageNames in the extras
+                    mHandler.sendMessage(PooledLambda.obtainMessage(AppOpsService::notifyOpChanged,
+                            AppOpsService.this, callbacks, OP_PLAY_AUDIO, changedUid, changedPkg));
+                }
+            }
+        }, packageSuspendFilter);
+
         PackageManagerInternal packageManagerInternal = LocalServices.getService(
                 PackageManagerInternal.class);
         packageManagerInternal.setExternalSourcesPolicy(