Merge "Create aconfig flag for enabling SDK system feature cache" into main
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java b/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java
index 73bff08..af02374 100644
--- a/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java
@@ -20,6 +20,7 @@
 import android.app.Instrumentation;
 import android.os.Bundle;
 import android.os.Debug;
+import android.os.Trace;
 import android.util.Log;
 
 import androidx.test.InstrumentationRegistry;
@@ -129,17 +130,23 @@
     }
 
     private void beginWarmup() {
+        Trace.beginSection("Warmup");
         mStartTimeNs = System.nanoTime();
         mIteration = 0;
         mState = WARMUP;
     }
 
+    private void endWarmup() {
+        Trace.endSection();
+    }
+
     private void beginBenchmark(long warmupDuration, int iterations) {
         if (ENABLE_PROFILING) {
             File f = new File(InstrumentationRegistry.getContext().getDataDir(), "benchprof");
             Log.d(TAG, "Tracing to: " + f.getAbsolutePath());
             Debug.startMethodTracingSampling(f.getAbsolutePath(), 16 * 1024 * 1024, 100);
         }
+        Trace.beginSection("Benchmark");
         mMaxIterations = (int) (TARGET_TEST_DURATION_NS / (warmupDuration / iterations));
         mMaxIterations = Math.min(MAX_TEST_ITERATIONS,
                 Math.max(mMaxIterations, MIN_TEST_ITERATIONS));
@@ -150,6 +157,10 @@
         mStartTimeNs = System.nanoTime();
     }
 
+    private void endBenchmark() {
+        Trace.endSection();
+    }
+
     private boolean startNextTestRun() {
         final long currentTime = System.nanoTime();
         mResults.add((currentTime - mStartTimeNs - mPausedDurationNs) / mMaxIterations);
@@ -165,6 +176,7 @@
                 return true;
             }
             mState = FINISHED;
+            endBenchmark();
             return false;
         }
         mPausedDurationNs = 0;
@@ -189,6 +201,7 @@
                 // don't yet have a target iteration count.
                 final long duration = System.nanoTime() - mStartTimeNs;
                 if (mIteration >= WARMUP_MIN_ITERATIONS && duration >= WARMUP_DURATION_NS) {
+                    endWarmup();
                     beginBenchmark(duration, mIteration);
                 }
                 return true;
@@ -208,6 +221,7 @@
                 mCustomizedIterations++;
                 if (mCustomizedIterations >= mMaxCustomizedIterations) {
                     mState = FINISHED;
+                    endBenchmark();
                     return false;
                 }
                 mCustomizedIterationListener.onStart(mCustomizedIterations);
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 59327c8..7862a36 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -2385,6 +2385,12 @@
     method @NonNull public static byte[] digest(@NonNull java.io.InputStream, @NonNull String) throws java.io.IOException, java.security.NoSuchAlgorithmException;
   }
 
+  public class Handler {
+    method @FlaggedApi("android.os.mainline_vcn_platform_api") public final boolean hasMessagesOrCallbacks();
+    method @FlaggedApi("android.os.mainline_vcn_platform_api") public final void removeCallbacksAndEqualMessages(@Nullable Object);
+    method @FlaggedApi("android.os.mainline_vcn_platform_api") public final void removeEqualMessages(int, @Nullable Object);
+  }
+
   public class IpcDataCache<Query, Result> extends android.app.PropertyInvalidatedCache<Query,Result> {
     ctor public IpcDataCache(int, @NonNull String, @NonNull String, @NonNull String, @NonNull android.os.IpcDataCache.QueryHandler<Query,Result>);
     method public static void disableForCurrentProcess(@NonNull String);
diff --git a/core/java/android/net/flags.aconfig b/core/java/android/net/flags.aconfig
index f7dc790..a30cd5c 100644
--- a/core/java/android/net/flags.aconfig
+++ b/core/java/android/net/flags.aconfig
@@ -28,3 +28,11 @@
     purpose: PURPOSE_BUGFIX
   }
 }
+
+flag {
+  name: "mdns_improvement_for_25q2"
+  is_exported: true
+  namespace: "android_core_networking"
+  description: "Flag for MDNS quality, reliability and performance improvement in 25Q2"
+  bug: "373270045"
+}
diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java
index d0828c3..eaecd34 100644
--- a/core/java/android/os/Handler.java
+++ b/core/java/android/os/Handler.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.util.Log;
 import android.util.Printer;
@@ -839,6 +840,7 @@
      *@hide
      */
     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    @TestApi
     @FlaggedApi(android.os.Flags.FLAG_MAINLINE_VCN_PLATFORM_API)
     public final void removeEqualMessages(int what, @Nullable Object object) {
         mQueue.removeEqualMessages(this, what, disallowNullArgumentIfShared(object));
@@ -872,6 +874,7 @@
      *@hide
      */
     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    @TestApi
     @FlaggedApi(android.os.Flags.FLAG_MAINLINE_VCN_PLATFORM_API)
     public final void removeCallbacksAndEqualMessages(@Nullable Object token) {
         mQueue.removeCallbacksAndEqualMessages(this, disallowNullArgumentIfShared(token));
@@ -889,6 +892,7 @@
      * @hide
      */
     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    @TestApi
     @FlaggedApi(android.os.Flags.FLAG_MAINLINE_VCN_PLATFORM_API)
     public final boolean hasMessagesOrCallbacks() {
         return mQueue.hasMessages(this);
diff --git a/framework-jarjar-rules.txt b/framework-jarjar-rules.txt
index 087378b..3da69e8 100644
--- a/framework-jarjar-rules.txt
+++ b/framework-jarjar-rules.txt
@@ -10,3 +10,6 @@
 
 # For Perfetto proto dependencies
 rule perfetto.protos.** android.internal.perfetto.protos.@1
+
+# For aconfig storage classes
+rule android.aconfig.storage.** android.internal.aconfig.storage.@1
diff --git a/nfc/Android.bp b/nfc/Android.bp
index b82dec8..c33665a 100644
--- a/nfc/Android.bp
+++ b/nfc/Android.bp
@@ -56,7 +56,7 @@
     ],
     defaults: ["framework-module-defaults"],
     sdk_version: "module_current",
-    min_sdk_version: "current",
+    min_sdk_version: "35", // Make it 36 once available.
     installable: true,
     optimize: {
         enabled: false,
diff --git a/nfc/api/current.txt b/nfc/api/current.txt
index 0ee81cb..c8c479a 100644
--- a/nfc/api/current.txt
+++ b/nfc/api/current.txt
@@ -211,7 +211,7 @@
     method public boolean isDefaultServiceForCategory(android.content.ComponentName, String);
     method @FlaggedApi("android.nfc.enable_card_emulation_euicc") public boolean isEuiccSupported();
     method public boolean registerAidsForService(android.content.ComponentName, String, java.util.List<java.lang.String>);
-    method @FlaggedApi("android.nfc.nfc_event_listener") public void registerNfcEventListener(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.cardemulation.CardEmulation.NfcEventListener);
+    method @FlaggedApi("android.nfc.nfc_event_listener") public void registerNfcEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.cardemulation.CardEmulation.NfcEventCallback);
     method @FlaggedApi("android.nfc.nfc_read_polling_loop") public boolean registerPollingLoopFilterForService(@NonNull android.content.ComponentName, @NonNull String, boolean);
     method @FlaggedApi("android.nfc.nfc_read_polling_loop") public boolean registerPollingLoopPatternFilterForService(@NonNull android.content.ComponentName, @NonNull String, boolean);
     method public boolean removeAidsForService(android.content.ComponentName, String);
@@ -221,7 +221,7 @@
     method public boolean setPreferredService(android.app.Activity, android.content.ComponentName);
     method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean setShouldDefaultToObserveModeForService(@NonNull android.content.ComponentName, boolean);
     method public boolean supportsAidPrefixRegistration();
-    method @FlaggedApi("android.nfc.nfc_event_listener") public void unregisterNfcEventListener(@NonNull android.nfc.cardemulation.CardEmulation.NfcEventListener);
+    method @FlaggedApi("android.nfc.nfc_event_listener") public void unregisterNfcEventCallback(@NonNull android.nfc.cardemulation.CardEmulation.NfcEventCallback);
     method @NonNull @RequiresPermission(android.Manifest.permission.NFC) public boolean unsetOffHostForService(@NonNull android.content.ComponentName);
     method public boolean unsetPreferredService(android.app.Activity);
     field @Deprecated public static final String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT";
@@ -244,7 +244,7 @@
     field public static final int SELECTION_MODE_PREFER_DEFAULT = 0; // 0x0
   }
 
-  @FlaggedApi("android.nfc.nfc_event_listener") public static interface CardEmulation.NfcEventListener {
+  @FlaggedApi("android.nfc.nfc_event_listener") public static interface CardEmulation.NfcEventCallback {
     method @FlaggedApi("android.nfc.nfc_event_listener") public default void onAidConflictOccurred(@NonNull String);
     method @FlaggedApi("android.nfc.nfc_event_listener") public default void onAidNotRouted(@NonNull String);
     method @FlaggedApi("android.nfc.nfc_event_listener") public default void onInternalErrorReported(int);
diff --git a/nfc/java/android/nfc/INfcCardEmulation.aidl b/nfc/java/android/nfc/INfcCardEmulation.aidl
index bb9fe95..00ceaa9 100644
--- a/nfc/java/android/nfc/INfcCardEmulation.aidl
+++ b/nfc/java/android/nfc/INfcCardEmulation.aidl
@@ -17,7 +17,7 @@
 package android.nfc;
 
 import android.content.ComponentName;
-import android.nfc.INfcEventListener;
+import android.nfc.INfcEventCallback;
 
 import android.nfc.cardemulation.AidGroup;
 import android.nfc.cardemulation.ApduServiceInfo;
@@ -60,6 +60,6 @@
     List<String> getRoutingStatus();
     void overwriteRoutingTable(int userHandle, String emptyAid, String protocol, String tech, String sc);
 
-    void registerNfcEventListener(in INfcEventListener listener);
-    void unregisterNfcEventListener(in INfcEventListener listener);
+    void registerNfcEventCallback(in INfcEventCallback listener);
+    void unregisterNfcEventCallback(in INfcEventCallback listener);
 }
diff --git a/nfc/java/android/nfc/INfcEventListener.aidl b/nfc/java/android/nfc/INfcEventCallback.aidl
similarity index 92%
rename from nfc/java/android/nfc/INfcEventListener.aidl
rename to nfc/java/android/nfc/INfcEventCallback.aidl
index 774d8f8..af1fa2fb 100644
--- a/nfc/java/android/nfc/INfcEventListener.aidl
+++ b/nfc/java/android/nfc/INfcEventCallback.aidl
@@ -5,7 +5,7 @@
 /**
  * @hide
  */
-oneway interface INfcEventListener {
+oneway interface INfcEventCallback {
     void onPreferredServiceChanged(in ComponentNameAndUser ComponentNameAndUser);
     void onObserveModeStateChanged(boolean isEnabled);
     void onAidConflictOccurred(in String aid);
diff --git a/nfc/java/android/nfc/cardemulation/CardEmulation.java b/nfc/java/android/nfc/cardemulation/CardEmulation.java
index e0bc15f..fee9c5b 100644
--- a/nfc/java/android/nfc/cardemulation/CardEmulation.java
+++ b/nfc/java/android/nfc/cardemulation/CardEmulation.java
@@ -39,7 +39,7 @@
 import android.nfc.Constants;
 import android.nfc.Flags;
 import android.nfc.INfcCardEmulation;
-import android.nfc.INfcEventListener;
+import android.nfc.INfcEventCallback;
 import android.nfc.NfcAdapter;
 import android.os.Build;
 import android.os.RemoteException;
@@ -1304,7 +1304,7 @@
 
     /** Listener for preferred service state changes. */
     @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
-    public interface NfcEventListener {
+    public interface NfcEventCallback {
         /**
          * This method is called when this package gains or loses preferred Nfc service status,
          * either the Default Wallet Role holder (see {@link
@@ -1327,7 +1327,10 @@
 
         /**
          * This method is called when an AID conflict is detected during an NFC transaction. This
-         * can happen when multiple services are registered for the same AID.
+         * can happen when multiple services are registered for the same AID. If your service is
+         * registered for this AID you may want to instruct users to bring your app to the
+         * foreground and ensure you call {@link #setPreferredService(Activity, ComponentName)}
+         * to ensure the transaction is routed to your service.
          *
          * @param aid The AID that is in conflict
          */
@@ -1377,10 +1380,10 @@
         default void onInternalErrorReported(@NfcInternalErrorType int errorType) {}
     }
 
-    private final ArrayMap<NfcEventListener, Executor> mNfcEventListeners = new ArrayMap<>();
+    private final ArrayMap<NfcEventCallback, Executor> mNfcEventCallbacks = new ArrayMap<>();
 
-    final INfcEventListener mINfcEventListener =
-            new INfcEventListener.Stub() {
+    final INfcEventCallback mINfcEventCallback =
+            new INfcEventCallback.Stub() {
                 public void onPreferredServiceChanged(ComponentNameAndUser componentNameAndUser) {
                     if (!android.nfc.Flags.nfcEventListener()) {
                         return;
@@ -1440,12 +1443,12 @@
                 }
 
                 interface ListenerCall {
-                    void invoke(NfcEventListener listener);
+                    void invoke(NfcEventCallback listener);
                 }
 
                 private void callListeners(ListenerCall listenerCall) {
-                    synchronized (mNfcEventListeners) {
-                        mNfcEventListeners.forEach(
+                    synchronized (mNfcEventCallbacks) {
+                        mNfcEventCallbacks.forEach(
                             (listener, executor) -> {
                                 executor.execute(() -> listenerCall.invoke(listener));
                             });
@@ -1460,34 +1463,34 @@
      * @param listener The listener to register
      */
     @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
-    public void registerNfcEventListener(
-            @NonNull @CallbackExecutor Executor executor, @NonNull NfcEventListener listener) {
+    public void registerNfcEventCallback(
+            @NonNull @CallbackExecutor Executor executor, @NonNull NfcEventCallback listener) {
         if (!android.nfc.Flags.nfcEventListener()) {
             return;
         }
-        synchronized (mNfcEventListeners) {
-            mNfcEventListeners.put(listener, executor);
-            if (mNfcEventListeners.size() == 1) {
-                callService(() -> sService.registerNfcEventListener(mINfcEventListener));
+        synchronized (mNfcEventCallbacks) {
+            mNfcEventCallbacks.put(listener, executor);
+            if (mNfcEventCallbacks.size() == 1) {
+                callService(() -> sService.registerNfcEventCallback(mINfcEventCallback));
             }
         }
     }
 
     /**
      * Unregister a preferred service listener that was previously registered with {@link
-     * #registerNfcEventListener(Executor, NfcEventListener)}
+     * #registerNfcEventCallback(Executor, NfcEventCallback)}
      *
      * @param listener The previously registered listener to unregister
      */
     @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
-    public void unregisterNfcEventListener(@NonNull NfcEventListener listener) {
+    public void unregisterNfcEventCallback(@NonNull NfcEventCallback listener) {
         if (!android.nfc.Flags.nfcEventListener()) {
             return;
         }
-        synchronized (mNfcEventListeners) {
-            mNfcEventListeners.remove(listener);
-            if (mNfcEventListeners.size() == 0) {
-                callService(() -> sService.unregisterNfcEventListener(mINfcEventListener));
+        synchronized (mNfcEventCallbacks) {
+            mNfcEventCallbacks.remove(listener);
+            if (mNfcEventCallbacks.size() == 0) {
+                callService(() -> sService.unregisterNfcEventCallback(mINfcEventCallback));
             }
         }
     }
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index bcfd8f6..75156ba 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -236,6 +236,9 @@
     /** Always keep remote bugreport files created in the last day. */
     private static final long REMOTE_MIN_KEEP_AGE = DateUtils.DAY_IN_MILLIS;
 
+    /** Minimum delay for sending last update notification */
+    private static final int DELAY_NOTIFICATION_MS = 250;
+
     private final Object mLock = new Object();
 
     /** Managed bugreport info (keyed by id) */
@@ -849,6 +852,7 @@
             Log.d(TAG, "Progress #" + info.id + ": " + percentageText);
         }
         info.lastProgress.set(progress);
+        info.lastUpdate.set(System.currentTimeMillis());
 
         sendForegroundabledNotification(info.id, builder.build());
     }
@@ -1368,6 +1372,16 @@
      */
     private void sendBugreportNotification(BugreportInfo info, boolean takingScreenshot) {
 
+        final long lastUpdate = System.currentTimeMillis() - info.lastUpdate.longValue();
+        if (lastUpdate < DELAY_NOTIFICATION_MS) {
+            Log.d(TAG, "Delaying final notification for "
+                    + (DELAY_NOTIFICATION_MS - lastUpdate) + " ms ");
+            mMainThreadHandler.postDelayed(() -> {
+                sendBugreportNotification(info, takingScreenshot);
+            }, DELAY_NOTIFICATION_MS - lastUpdate);
+            return;
+        }
+
         // Since adding the details can take a while, do it before notifying user.
         addDetailsToZipFile(info);
 
@@ -1388,6 +1402,7 @@
         final Notification.Builder builder = newBaseNotification(mContext)
                 .setContentTitle(title)
                 .setTicker(title)
+                .setProgress(100 /* max value of progress percentage */, 100, false)
                 .setOnlyAlertOnce(false)
                 .setContentText(content);
 
@@ -2426,7 +2441,6 @@
             }
         }
         info.progress.set(progress);
-        info.lastUpdate.set(System.currentTimeMillis());
 
         updateProgress(info);
     }
diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
index 050a370..7bda2ea 100644
--- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
+++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
@@ -193,7 +193,7 @@
         mService.mScreenshotDelaySec = SCREENSHOT_DELAY_SECONDS;
         // Dup the fds which are passing to startBugreport function.
         Mockito.doAnswer(invocation -> {
-            final boolean isScreenshotRequested = invocation.getArgument(6);
+            final boolean isScreenshotRequested = invocation.getArgument(7);
             if (isScreenshotRequested) {
                 mScreenshotFd = ParcelFileDescriptor.dup(invocation.getArgument(3));
             }
@@ -250,7 +250,22 @@
         mIDumpstateListener.onProgress(300);
         assertProgressNotification(mProgressTitle, 99);
 
-        Bundle extras = sendBugreportFinishedAndGetSharedIntent(mBugreportId);
+        Bundle extras = sendBugreportFinishedAndGetSharedIntent(mBugreportId, 1);
+        assertActionSendMultiple(extras);
+
+        assertServiceNotRunning();
+    }
+
+    @Test
+    public void testStressProgress() throws Exception {
+        sendBugreportStarted();
+        waitForScreenshotButtonEnabled(true);
+
+        for (int i = 0; i <= 1000; i++) {
+            mIDumpstateListener.onProgress(i);
+        }
+        sendBugreportFinished();
+        Bundle extras = acceptBugreportAndGetSharedIntent(mBugreportId, 1);
         assertActionSendMultiple(extras);
 
         assertServiceNotRunning();
@@ -277,7 +292,7 @@
         assertScreenshotButtonEnabled(false);
         waitForScreenshotButtonEnabled(true);
 
-        Bundle extras = sendBugreportFinishedAndGetSharedIntent(mBugreportId);
+        Bundle extras = sendBugreportFinishedAndGetSharedIntent(mBugreportId, 2);
         assertActionSendMultiple(extras, NO_NAME, NO_TITLE, NO_DESCRIPTION, 1);
 
         assertServiceNotRunning();
@@ -294,7 +309,7 @@
         // There's no indication in the UI about the screenshot finish, so just sleep like a baby...
         sleep(SAFE_SCREENSHOT_DELAY * DateUtils.SECOND_IN_MILLIS);
 
-        Bundle extras = acceptBugreportAndGetSharedIntent(mBugreportId);
+        Bundle extras = acceptBugreportAndGetSharedIntent(mBugreportId, 2);
         assertActionSendMultiple(extras, NO_NAME, NO_TITLE, NO_DESCRIPTION, 1);
 
         assertServiceNotRunning();
@@ -328,7 +343,7 @@
 
         assertProgressNotification(NEW_NAME, 00.00f);
 
-        Bundle extras = sendBugreportFinishedAndGetSharedIntent(TITLE);
+        Bundle extras = sendBugreportFinishedAndGetSharedIntent(TITLE, 1);
         assertActionSendMultiple(extras, NEW_NAME, TITLE, mDescription, 0);
 
         assertServiceNotRunning();
@@ -363,7 +378,7 @@
 
         assertProgressNotification(NEW_NAME, 00.00f);
 
-        Bundle extras = sendBugreportFinishedAndGetSharedIntent(TITLE);
+        Bundle extras = sendBugreportFinishedAndGetSharedIntent(TITLE, 1);
         assertActionSendMultiple(extras, NEW_NAME, TITLE, mDescription, 0);
 
         assertServiceNotRunning();
@@ -390,7 +405,7 @@
         detailsUi.descField.setText(mDescription);
         detailsUi.clickOk();
 
-        Bundle extras = sendBugreportFinishedAndGetSharedIntent(mBugreportId);
+        Bundle extras = sendBugreportFinishedAndGetSharedIntent(mBugreportId, 1);
         assertActionSendMultiple(extras, NO_NAME, NO_TITLE, mDescription, 0);
 
         assertServiceNotRunning();
@@ -441,7 +456,7 @@
         detailsUi.clickOk();
 
         // Finally, share bugreport.
-        Bundle extras = acceptBugreportAndGetSharedIntent(mBugreportId);
+        Bundle extras = acceptBugreportAndGetSharedIntent(mBugreportId, 1);
         assertActionSendMultiple(extras, NO_NAME, TITLE, mDescription, 0);
 
         assertServiceNotRunning();
@@ -504,7 +519,7 @@
         mUiBot.click(ok, "ok");
 
         // Share the bugreport.
-        mUiBot.chooseActivity(UI_NAME);
+        mUiBot.chooseActivity(UI_NAME, mContext, 1);
         Bundle extras = mListener.getExtras();
         assertActionSendMultiple(extras);
 
@@ -531,7 +546,7 @@
         sendBugreportFinished();
         killService();
         assertServiceNotRunning();
-        Bundle extras = acceptBugreportAndGetSharedIntent(mBugreportId);
+        Bundle extras = acceptBugreportAndGetSharedIntent(mBugreportId, 1);
         assertActionSendMultiple(extras);
     }
 
@@ -618,45 +633,49 @@
      * Sends a "bugreport finished" event and waits for the result.
      *
      * @param id The bugreport id for finished notification string title substitution.
+     * @param count Number of files to be shared
      * @return extras sent in the shared intent.
      */
-    private Bundle sendBugreportFinishedAndGetSharedIntent(int id) throws Exception {
+    private Bundle sendBugreportFinishedAndGetSharedIntent(int id, int count) throws Exception {
         sendBugreportFinished();
-        return acceptBugreportAndGetSharedIntent(id);
+        return acceptBugreportAndGetSharedIntent(id, count);
     }
 
     /**
      * Sends a "bugreport finished" event and waits for the result.
      *
      * @param notificationTitle The title of finished notification.
+     * @param count Number of files to be shared
      * @return extras sent in the shared intent.
      */
-    private Bundle sendBugreportFinishedAndGetSharedIntent(String notificationTitle)
+    private Bundle sendBugreportFinishedAndGetSharedIntent(String notificationTitle, int count)
             throws Exception {
         sendBugreportFinished();
-        return acceptBugreportAndGetSharedIntent(notificationTitle);
+        return acceptBugreportAndGetSharedIntent(notificationTitle, count);
     }
 
     /**
      * Accepts the notification to share the finished bugreport and waits for the result.
      *
      * @param id The bugreport id for finished notification string title substitution.
+     * @param count Number of files to be shared
      * @return extras sent in the shared intent.
      */
-    private Bundle acceptBugreportAndGetSharedIntent(int id) {
+    private Bundle acceptBugreportAndGetSharedIntent(int id, int count) {
         final String notificationTitle = mContext.getString(R.string.bugreport_finished_title, id);
-        return acceptBugreportAndGetSharedIntent(notificationTitle);
+        return acceptBugreportAndGetSharedIntent(notificationTitle, count);
     }
 
     /**
      * Accepts the notification to share the finished bugreport and waits for the result.
      *
      * @param notificationTitle The title of finished notification.
+     * @param count Number of files to be shared
      * @return extras sent in the shared intent.
      */
-    private Bundle acceptBugreportAndGetSharedIntent(String notificationTitle) {
+    private Bundle acceptBugreportAndGetSharedIntent(String notificationTitle, int count) {
         mUiBot.clickOnNotification(notificationTitle);
-        mUiBot.chooseActivity(UI_NAME);
+        mUiBot.chooseActivity(UI_NAME, mContext, count);
         return mListener.getExtras();
     }
 
diff --git a/packages/Shell/tests/src/com/android/shell/UiBot.java b/packages/Shell/tests/src/com/android/shell/UiBot.java
index ce9f70d..60008a3 100644
--- a/packages/Shell/tests/src/com/android/shell/UiBot.java
+++ b/packages/Shell/tests/src/com/android/shell/UiBot.java
@@ -18,9 +18,12 @@
 
 import android.app.Instrumentation;
 import android.app.StatusBarManager;
+import android.content.Context;
+import android.content.res.Resources;
 import android.os.SystemClock;
 import android.text.format.DateUtils;
 import android.util.Log;
+import android.util.PluralsMessageFormatter;
 
 import androidx.test.uiautomator.By;
 import androidx.test.uiautomator.UiDevice;
@@ -34,7 +37,9 @@
 import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertTrue;
 
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * A helper class for UI-related testing tasks.
@@ -206,11 +211,26 @@
      *
      * @param name name of the activity as displayed in the UI (typically the value set by
      *            {@code android:label} in the manifest).
+     * @param context Context of the target application
+     * @param count Number of files to be shared
      */
-    public void chooseActivity(String name) {
+    public void chooseActivity(String name, Context context, int count) {
         // It uses an intent chooser now, so just getting the activity by text is enough...
-        final String share = mInstrumentation.getContext().getString(
-                com.android.internal.R.string.share);
+        Resources res = null;
+        try {
+            res = context.getPackageManager()
+                    .getResourcesForApplication("com.android.intentresolver");
+        } catch (Exception e)  {
+            assertNotNull("could not get resources for com.android.intentresolver", res);
+        }
+        /* Resource read is defined as a string which contains a plural
+         * which needs some formatting */
+        Map<String, Object> arguments = new HashMap<>();
+        arguments.put("count", count);
+        final String share = PluralsMessageFormatter.format(
+                res,
+                arguments,
+                res.getIdentifier("sharing_files", "string", "com.android.intentresolver"));
         boolean gotIt = mDevice.wait(Until.hasObject(By.text(share)), mTimeout);
         assertTrue("could not get share activity (" + share + ")", gotIt);
         swipeUp();
diff --git a/services/art-wear-profile b/services/art-wear-profile
index 47bdb13..42c4a01 100644
--- a/services/art-wear-profile
+++ b/services/art-wear-profile
@@ -7419,7 +7419,7 @@
 PLcom/android/server/app/GameManagerService;->updateConfigsForUser(IZ[Ljava/lang/String;)V
 PLcom/android/server/app/GameManagerService;->writeGameModeInterventionsToFile(I)V
 PLcom/android/server/app/GameManagerSettings;-><init>(Ljava/io/File;)V
-HPLcom/android/server/app/GameManagerSettings;->getConfigOverride(Ljava/lang/String;)Lcom/android/server/app/GameManagerService$GamePackageConfiguration;
+HPLcom/android/server/app/GameManagerSettings;->getConfigOverrideLocked(Ljava/lang/String;)Lcom/android/server/app/GameManagerService$GamePackageConfiguration;
 HPLcom/android/server/app/GameManagerSettings;->getGameModeLocked(Ljava/lang/String;)I
 PLcom/android/server/app/GameManagerSettings;->readPersistentDataLocked()Z
 PLcom/android/server/appbinding/AppBindingConstants;-><init>(Ljava/lang/String;)V
diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java
index 5f637a3..58ef814 100644
--- a/services/core/java/com/android/server/app/GameManagerService.java
+++ b/services/core/java/com/android/server/app/GameManagerService.java
@@ -1422,10 +1422,10 @@
             }
             final GameManagerSettings settings = mSettings.get(userId);
             // look for the existing GamePackageConfiguration override
-            configOverride = settings.getConfigOverride(packageName);
+            configOverride = settings.getConfigOverrideLocked(packageName);
             if (configOverride == null) {
                 configOverride = new GamePackageConfiguration(packageName);
-                settings.setConfigOverride(packageName, configOverride);
+                settings.setConfigOverrideLocked(packageName, configOverride);
             }
         }
         GamePackageConfiguration.GameModeConfiguration internalConfig =
@@ -1758,10 +1758,10 @@
             }
             final GameManagerSettings settings = mSettings.get(userId);
             // look for the existing GamePackageConfiguration override
-            configOverride = settings.getConfigOverride(packageName);
+            configOverride = settings.getConfigOverrideLocked(packageName);
             if (configOverride == null) {
                 configOverride = new GamePackageConfiguration(packageName);
-                settings.setConfigOverride(packageName, configOverride);
+                settings.setConfigOverrideLocked(packageName, configOverride);
             }
         }
         // modify GameModeConfiguration intervention settings
@@ -1800,7 +1800,7 @@
             }
             final GameManagerSettings settings = mSettings.get(userId);
             if (gameModeToReset != -1) {
-                final GamePackageConfiguration configOverride = settings.getConfigOverride(
+                final GamePackageConfiguration configOverride = settings.getConfigOverrideLocked(
                         packageName);
                 if (configOverride == null) {
                     return;
@@ -1811,10 +1811,10 @@
                 }
                 configOverride.removeModeConfig(gameModeToReset);
                 if (!configOverride.hasActiveGameModeConfig()) {
-                    settings.removeConfigOverride(packageName);
+                    settings.removeConfigOverrideLocked(packageName);
                 }
             } else {
-                settings.removeConfigOverride(packageName);
+                settings.removeConfigOverrideLocked(packageName);
             }
         }
 
@@ -2029,7 +2029,7 @@
 
         synchronized (mLock) {
             if (mSettings.containsKey(userId)) {
-                overrideConfig = mSettings.get(userId).getConfigOverride(packageName);
+                overrideConfig = mSettings.get(userId).getConfigOverrideLocked(packageName);
             }
         }
         if (overrideConfig == null || config == null) {
@@ -2074,7 +2074,7 @@
                                 }
                                 synchronized (mLock) {
                                     if (mSettings.containsKey(userId)) {
-                                        mSettings.get(userId).removeGame(packageName);
+                                        mSettings.get(userId).removeGameLocked(packageName);
                                     }
                                     sendUserMessage(userId, WRITE_SETTINGS,
                                             Intent.ACTION_PACKAGE_REMOVED, WRITE_DELAY_MILLIS);
diff --git a/services/core/java/com/android/server/app/GameManagerSettings.java b/services/core/java/com/android/server/app/GameManagerSettings.java
index b084cf3..c57a1f7 100644
--- a/services/core/java/com/android/server/app/GameManagerSettings.java
+++ b/services/core/java/com/android/server/app/GameManagerSettings.java
@@ -116,7 +116,7 @@
      * Removes all game settings of a given package.
      * This operation must be synced with an external lock.
      */
-    void removeGame(String packageName) {
+    void removeGameLocked(String packageName) {
         mGameModes.remove(packageName);
         mConfigOverrides.remove(packageName);
     }
@@ -125,7 +125,7 @@
      * Returns the game config override of a given package or null if absent.
      * This operation must be synced with an external lock.
      */
-    GamePackageConfiguration getConfigOverride(String packageName) {
+    GamePackageConfiguration getConfigOverrideLocked(String packageName) {
         return mConfigOverrides.get(packageName);
     }
 
@@ -133,7 +133,7 @@
      * Sets the game config override of a given package.
      * This operation must be synced with an external lock.
      */
-    void setConfigOverride(String packageName, GamePackageConfiguration configOverride) {
+    void setConfigOverrideLocked(String packageName, GamePackageConfiguration configOverride) {
         mConfigOverrides.put(packageName, configOverride);
     }
 
@@ -141,7 +141,7 @@
      * Removes the game mode config override of a given package.
      * This operation must be synced with an external lock.
      */
-    void removeConfigOverride(String packageName) {
+    void removeConfigOverrideLocked(String packageName) {
         mConfigOverrides.remove(packageName);
     }
 
diff --git a/services/core/java/com/android/server/policy/AppOpsPolicy.java b/services/core/java/com/android/server/policy/AppOpsPolicy.java
index ecffd38..3f9144f 100644
--- a/services/core/java/com/android/server/policy/AppOpsPolicy.java
+++ b/services/core/java/com/android/server/policy/AppOpsPolicy.java
@@ -136,7 +136,8 @@
 
         final LocationManagerInternal locationManagerInternal = LocalServices.getService(
                 LocationManagerInternal.class);
-        locationManagerInternal.setLocationPackageTagsListener(
+        if (locationManagerInternal != null) {
+            locationManagerInternal.setLocationPackageTagsListener(
                 (uid, packageTagsList) -> {
                     synchronized (mLock) {
                         if (packageTagsList.isEmpty()) {
@@ -158,6 +159,7 @@
                                 mLocationTags);
                     }
                 });
+        }
 
         final IntentFilter intentFilter = new IntentFilter();
         intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 673d82d..fcb6036 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3254,7 +3254,8 @@
             // just kill it. And if it is a window of foreground activity, the activity can be
             // restarted automatically if needed.
             Slog.w(TAG, "Exception thrown during dispatchAppVisibility " + this, e);
-            if (android.os.Process.getUidForPid(mSession.mPid) == mSession.mUid) {
+            if (android.os.Process.getUidForPid(mSession.mPid) == mSession.mUid
+                    && android.os.Process.getThreadGroupLeader(mSession.mPid) == mSession.mPid) {
                 android.os.Process.killProcess(mSession.mPid);
             }
         }
diff --git a/services/tests/servicestests/src/com/android/server/app/GameManagerServiceSettingsTests.java b/services/tests/servicestests/src/com/android/server/app/GameManagerServiceSettingsTests.java
index fde3422..17f5ebb 100644
--- a/services/tests/servicestests/src/com/android/server/app/GameManagerServiceSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/app/GameManagerServiceSettingsTests.java
@@ -130,9 +130,9 @@
         assertEquals(GameManager.GAME_MODE_STANDARD, settings.getGameModeLocked(PACKAGE_NAME_4));
 
         // test game mode configs
-        assertNull(settings.getConfigOverride(PACKAGE_NAME_1));
-        assertNull(settings.getConfigOverride(PACKAGE_NAME_3));
-        GamePackageConfiguration config = settings.getConfigOverride(PACKAGE_NAME_2);
+        assertNull(settings.getConfigOverrideLocked(PACKAGE_NAME_1));
+        assertNull(settings.getConfigOverrideLocked(PACKAGE_NAME_3));
+        GamePackageConfiguration config = settings.getConfigOverrideLocked(PACKAGE_NAME_2);
         assertNotNull(config);
 
         assertNull(config.getGameModeConfiguration(GameManager.GAME_MODE_STANDARD));
@@ -152,7 +152,7 @@
         assertEquals(batteryConfig.getFpsStr(), GameModeConfiguration.DEFAULT_FPS);
         assertFalse(batteryConfig.getUseAngle());
 
-        config = settings.getConfigOverride(PACKAGE_NAME_4);
+        config = settings.getConfigOverrideLocked(PACKAGE_NAME_4);
         assertNotNull(config);
         GameModeConfiguration customConfig = config.getGameModeConfiguration(
                 GameManager.GAME_MODE_CUSTOM);
@@ -177,7 +177,7 @@
         GameManagerSettings settings = new GameManagerSettings(context.getFilesDir());
         assertTrue(settings.readPersistentDataLocked());
 
-        final GamePackageConfiguration config = settings.getConfigOverride(PACKAGE_NAME_1);
+        final GamePackageConfiguration config = settings.getConfigOverrideLocked(PACKAGE_NAME_1);
         assertNotNull(config);
         final GameModeConfiguration batteryConfig = config.getGameModeConfiguration(
                 GameManager.GAME_MODE_BATTERY);
@@ -218,7 +218,7 @@
         assertEquals(2, settings.getGameModeLocked(PACKAGE_NAME_2));
         assertEquals(3, settings.getGameModeLocked(PACKAGE_NAME_3));
 
-        final GamePackageConfiguration config = settings.getConfigOverride(PACKAGE_NAME_2);
+        final GamePackageConfiguration config = settings.getConfigOverrideLocked(PACKAGE_NAME_2);
         assertNotNull(config);
         final GameModeConfiguration batteryConfig = config.getGameModeConfiguration(
                 GameManager.GAME_MODE_BATTERY);
@@ -248,7 +248,7 @@
         GameModeConfiguration batteryConfig = config.getOrAddDefaultGameModeConfiguration(
                 GameManager.GAME_MODE_BATTERY);
         batteryConfig.setScaling(0.77f);
-        settings.setConfigOverride(PACKAGE_NAME_2, config);
+        settings.setConfigOverrideLocked(PACKAGE_NAME_2, config);
 
         // set config for app4
         config = new GamePackageConfiguration(PACKAGE_NAME_4);
@@ -256,15 +256,15 @@
                 GameManager.GAME_MODE_CUSTOM);
         customConfig.setScaling(0.4f);
         customConfig.setFpsStr("30");
-        settings.setConfigOverride(PACKAGE_NAME_4, config);
+        settings.setConfigOverrideLocked(PACKAGE_NAME_4, config);
 
         settings.writePersistentDataLocked();
 
         // clear the settings in memory
-        settings.removeGame(PACKAGE_NAME_1);
-        settings.removeGame(PACKAGE_NAME_2);
-        settings.removeGame(PACKAGE_NAME_3);
-        settings.removeGame(PACKAGE_NAME_4);
+        settings.removeGameLocked(PACKAGE_NAME_1);
+        settings.removeGameLocked(PACKAGE_NAME_2);
+        settings.removeGameLocked(PACKAGE_NAME_3);
+        settings.removeGameLocked(PACKAGE_NAME_4);
 
         // read back in and verify
         assertTrue(settings.readPersistentDataLocked());
@@ -273,9 +273,9 @@
         assertEquals(1, settings.getGameModeLocked(PACKAGE_NAME_3));
         assertEquals(1, settings.getGameModeLocked(PACKAGE_NAME_4));
 
-        config = settings.getConfigOverride(PACKAGE_NAME_1);
+        config = settings.getConfigOverrideLocked(PACKAGE_NAME_1);
         assertNull(config);
-        config = settings.getConfigOverride(PACKAGE_NAME_2);
+        config = settings.getConfigOverrideLocked(PACKAGE_NAME_2);
         assertNotNull(config);
         batteryConfig = config.getGameModeConfiguration(GameManager.GAME_MODE_BATTERY);
         assertNotNull(batteryConfig);
@@ -292,7 +292,7 @@
         assertEquals(performanceConfig.getFpsStr(), "60");
         assertTrue(performanceConfig.getUseAngle());
 
-        config = settings.getConfigOverride(PACKAGE_NAME_4);
+        config = settings.getConfigOverrideLocked(PACKAGE_NAME_4);
         assertNotNull(config);
         customConfig = config.getGameModeConfiguration(GameManager.GAME_MODE_CUSTOM);
         assertNotNull(customConfig);