Merge "Address API feedback" into rvc-dev
diff --git a/apex/media/framework/java/android/media/MediaParser.java b/apex/media/framework/java/android/media/MediaParser.java
index a4f7b5b..b219fd41 100644
--- a/apex/media/framework/java/android/media/MediaParser.java
+++ b/apex/media/framework/java/android/media/MediaParser.java
@@ -54,6 +54,7 @@
 
 import java.io.EOFException;
 import java.io.IOException;
+import java.io.InterruptedIOException;
 import java.nio.ByteBuffer;
 import java.util.Collections;
 import java.util.HashMap;
@@ -119,7 +120,7 @@
  *
  *     @Override
  *     public void onSampleData(int trackIndex, @NonNull InputReader inputReader)
- *         throws IOException, InterruptedException {
+ *         throws IOException {
  *       int numberOfBytesToRead = (int) inputReader.getLength();
  *       if (videoTrackIndex != trackIndex) {
  *         // Discard contents.
@@ -310,8 +311,7 @@
          *     of the input has been reached.
          * @throws java.io.IOException If an error occurs reading from the source.
          */
-        int read(@NonNull byte[] buffer, int offset, int readLength)
-                throws IOException, InterruptedException;
+        int read(@NonNull byte[] buffer, int offset, int readLength) throws IOException;
 
         /** Returns the current read position (byte offset) in the stream. */
         long getPosition();
@@ -373,11 +373,8 @@
          * @param trackIndex The index of the track to which the sample data corresponds.
          * @param inputReader The {@link InputReader} from which to read the data.
          * @throws IOException If an exception occurs while reading from {@code inputReader}.
-         * @throws InterruptedException If an interruption occurs while reading from {@code
-         *     inputReader}.
          */
-        void onSampleData(int trackIndex, @NonNull InputReader inputReader)
-                throws IOException, InterruptedException;
+        void onSampleData(int trackIndex, @NonNull InputReader inputReader) throws IOException;
 
         /**
          * Called once all the data of a sample has been passed to {@link #onSampleData}.
@@ -717,8 +714,7 @@
      * @throws UnrecognizedInputFormatException If the format cannot be recognized by any of the
      *     underlying parser implementations.
      */
-    public boolean advance(@NonNull SeekableInputReader seekableInputReader)
-            throws IOException, InterruptedException {
+    public boolean advance(@NonNull SeekableInputReader seekableInputReader) throws IOException {
         if (mExtractorInput == null) {
             // TODO: For efficiency, the same implementation should be used, by providing a
             // clearBuffers() method, or similar.
@@ -748,8 +744,10 @@
                         }
                     } catch (EOFException e) {
                         // Do nothing.
-                    } catch (IOException | InterruptedException e) {
-                        throw new IllegalStateException(e);
+                    } catch (InterruptedException e) {
+                        // TODO: Remove this exception replacement once we update the ExoPlayer
+                        // version.
+                        throw new InterruptedIOException();
                     } finally {
                         mExtractorInput.resetPeekPosition();
                     }
@@ -767,7 +765,13 @@
         }
 
         mPositionHolder.position = seekableInputReader.getPosition();
-        int result = mExtractor.read(mExtractorInput, mPositionHolder);
+        int result = 0;
+        try {
+            result = mExtractor.read(mExtractorInput, mPositionHolder);
+        } catch (InterruptedException e) {
+            // TODO: Remove this exception replacement once we update the ExoPlayer version.
+            throw new InterruptedIOException();
+        }
         if (result == Extractor.RESULT_END_OF_INPUT) {
             return false;
         }
@@ -853,13 +857,7 @@
 
         @Override
         public int read(byte[] buffer, int offset, int readLength) throws IOException {
-            // TODO: Reevaluate interruption in Input.
-            try {
-                return mInputReader.read(buffer, offset, readLength);
-            } catch (InterruptedException e) {
-                // TODO: Remove.
-                throw new RuntimeException();
-            }
+            return mInputReader.read(buffer, offset, readLength);
         }
 
         @Override
@@ -926,7 +924,7 @@
 
         @Override
         public int sampleData(ExtractorInput input, int length, boolean allowEndOfInput)
-                throws IOException, InterruptedException {
+                throws IOException {
             mScratchExtractorInputAdapter.setExtractorInput(input, length);
             long positionBeforeReading = mScratchExtractorInputAdapter.getPosition();
             mOutputConsumer.onSampleData(mTrackIndex, mScratchExtractorInputAdapter);
@@ -938,7 +936,7 @@
             mScratchParsableByteArrayAdapter.resetWithByteArray(data, length);
             try {
                 mOutputConsumer.onSampleData(mTrackIndex, mScratchParsableByteArrayAdapter);
-            } catch (IOException | InterruptedException e) {
+            } catch (IOException e) {
                 // Unexpected.
                 throw new RuntimeException(e);
             }
@@ -967,9 +965,14 @@
         // Input implementation.
 
         @Override
-        public int read(byte[] buffer, int offset, int readLength)
-                throws IOException, InterruptedException {
-            int readBytes = mExtractorInput.read(buffer, offset, readLength);
+        public int read(byte[] buffer, int offset, int readLength) throws IOException {
+            int readBytes = 0;
+            try {
+                readBytes = mExtractorInput.read(buffer, offset, readLength);
+            } catch (InterruptedException e) {
+                // TODO: Remove this exception replacement once we update the ExoPlayer version.
+                throw new InterruptedIOException();
+            }
             mCurrentPosition += readBytes;
             return readBytes;
         }
diff --git a/api/current.txt b/api/current.txt
index 7acbdb4..9c2007c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -26403,7 +26403,7 @@
   }
 
   public final class MediaParser {
-    method public boolean advance(@NonNull android.media.MediaParser.SeekableInputReader) throws java.io.IOException, java.lang.InterruptedException;
+    method public boolean advance(@NonNull android.media.MediaParser.SeekableInputReader) throws java.io.IOException;
     method @NonNull public static android.media.MediaParser create(@NonNull android.media.MediaParser.OutputConsumer, @NonNull java.lang.String...);
     method @NonNull public static android.media.MediaParser createByName(@NonNull String, @NonNull android.media.MediaParser.OutputConsumer);
     method @Nullable public String getParserName();
@@ -26435,12 +26435,12 @@
   public static interface MediaParser.InputReader {
     method public long getLength();
     method public long getPosition();
-    method public int read(@NonNull byte[], int, int) throws java.io.IOException, java.lang.InterruptedException;
+    method public int read(@NonNull byte[], int, int) throws java.io.IOException;
   }
 
   public static interface MediaParser.OutputConsumer {
     method public void onSampleCompleted(int, long, int, int, int, @Nullable android.media.MediaCodec.CryptoInfo);
-    method public void onSampleData(int, @NonNull android.media.MediaParser.InputReader) throws java.io.IOException, java.lang.InterruptedException;
+    method public void onSampleData(int, @NonNull android.media.MediaParser.InputReader) throws java.io.IOException;
     method public void onSeekMap(@NonNull android.media.MediaParser.SeekMap);
     method public void onTrackData(int, @NonNull android.media.MediaParser.TrackData);
     method public void onTracksFound(int);
diff --git a/api/system-current.txt b/api/system-current.txt
index 379ae57..9f2953c 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -11523,7 +11523,7 @@
   public class SmsMessage {
     method @Nullable public static android.telephony.SmsMessage createFromNativeSmsSubmitPdu(@NonNull byte[], boolean);
     method @Nullable public static android.telephony.SmsMessage.SubmitPdu getSmsPdu(int, int, @Nullable String, @NonNull String, @NonNull String, long);
-    method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public static byte[] getSubmitPduEncodedMessage(boolean, @NonNull String, @NonNull String, int, int, int, int, int, int);
+    method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public static byte[] getSubmitPduEncodedMessage(boolean, @NonNull String, @NonNull String, int, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0, to=255) int, @IntRange(from=1, to=255) int, @IntRange(from=1, to=255) int);
   }
 
   public class SubscriptionInfo implements android.os.Parcelable {
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index e9cdbf28..8c3eef2 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -748,5 +748,4 @@
     void clearMimeGroup(String packageName, String group);
 
     List<String> getMimeGroup(String packageName, String group);
-
 }
diff --git a/core/java/com/android/internal/accessibility/common/ShortcutConstants.java b/core/java/com/android/internal/accessibility/common/ShortcutConstants.java
new file mode 100644
index 0000000..1daa505
--- /dev/null
+++ b/core/java/com/android/internal/accessibility/common/ShortcutConstants.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.accessibility.common;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Collection of common constants for accessibility shortcut.
+ */
+public final class ShortcutConstants {
+    private ShortcutConstants() {}
+
+    public static final char SERVICES_SEPARATOR = ':';
+    public static final float DISABLED_ALPHA = 0.5f;
+    public static final float ENABLED_ALPHA = 1.0f;
+
+    /**
+     * Annotation for different user shortcut type UI type.
+     *
+     * {@code DEFAULT} for displaying default value.
+     * {@code SOFTWARE} for displaying specifying the accessibility services or features which
+     * choose accessibility button in the navigation bar as preferred shortcut.
+     * {@code HARDWARE} for displaying specifying the accessibility services or features which
+     * choose accessibility shortcut as preferred shortcut.
+     * {@code TRIPLETAP} for displaying specifying magnification to be toggled via quickly
+     * tapping screen 3 times as preferred shortcut.
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+            UserShortcutType.DEFAULT,
+            UserShortcutType.SOFTWARE,
+            UserShortcutType.HARDWARE,
+            UserShortcutType.TRIPLETAP,
+    })
+    public @interface UserShortcutType {
+        int DEFAULT = 0;
+        int SOFTWARE = 1; // 1 << 0
+        int HARDWARE = 2; // 1 << 1
+        int TRIPLETAP = 4; // 1 << 2
+    }
+
+    /**
+     * Annotation for different accessibilityService fragment UI type.
+     *
+     * {@code LEGACY} for displaying appearance aligned with sdk version Q accessibility service
+     * page, but only hardware shortcut allowed and under service in version Q or early.
+     * {@code INVISIBLE} for displaying appearance without switch bar.
+     * {@code INTUITIVE} for displaying appearance with version R accessibility design.
+     * {@code BOUNCE} for displaying appearance with pop-up action.
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+            AccessibilityServiceFragmentType.LEGACY,
+            AccessibilityServiceFragmentType.INVISIBLE,
+            AccessibilityServiceFragmentType.INTUITIVE,
+            AccessibilityServiceFragmentType.BOUNCE,
+    })
+    public @interface AccessibilityServiceFragmentType {
+        int LEGACY = 0;
+        int INVISIBLE = 1;
+        int INTUITIVE = 2;
+        int BOUNCE = 3;
+    }
+
+    /**
+     * Annotation for different shortcut menu mode.
+     *
+     * {@code LAUNCH} for clicking list item to trigger the service callback.
+     * {@code EDIT} for clicking list item and save button to disable the service.
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+            ShortcutMenuMode.LAUNCH,
+            ShortcutMenuMode.EDIT,
+    })
+    public @interface ShortcutMenuMode {
+        int LAUNCH = 0;
+        int EDIT = 1;
+    }
+
+    /**
+     * Annotation for align the element index of white listing feature
+     * {@code WHITE_LISTING_FEATURES}.
+     *
+     * {@code COMPONENT_ID} is to get the service component name.
+     * {@code LABEL_ID} is to get the service label text.
+     * {@code ICON_ID} is to get the service icon.
+     * {@code FRAGMENT_TYPE} is to get the service fragment type.
+     * {@code SETTINGS_KEY} is to get the service settings key.
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+            WhiteListingFeatureElementIndex.COMPONENT_ID,
+            WhiteListingFeatureElementIndex.LABEL_ID,
+            WhiteListingFeatureElementIndex.ICON_ID,
+            WhiteListingFeatureElementIndex.FRAGMENT_TYPE,
+            WhiteListingFeatureElementIndex.SETTINGS_KEY,
+    })
+    public @interface WhiteListingFeatureElementIndex {
+        int COMPONENT_ID = 0;
+        int LABEL_ID = 1;
+        int ICON_ID = 2;
+        int FRAGMENT_TYPE = 3;
+        int SETTINGS_KEY = 4;
+    }
+}
diff --git a/core/java/com/android/internal/accessibility/util/AccessibilityUtils.java b/core/java/com/android/internal/accessibility/util/AccessibilityUtils.java
new file mode 100644
index 0000000..d0ead5e
--- /dev/null
+++ b/core/java/com/android/internal/accessibility/util/AccessibilityUtils.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.accessibility.util;
+import static com.android.internal.accessibility.common.ShortcutConstants.AccessibilityServiceFragmentType;
+import static com.android.internal.accessibility.common.ShortcutConstants.SERVICES_SEPARATOR;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.Build;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.ArraySet;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Collection of utilities for accessibility service.
+ */
+public final class AccessibilityUtils {
+    private AccessibilityUtils() {}
+
+    /**
+     * Returns the set of enabled accessibility services for userId. If there are no
+     * services, it returns the unmodifiable {@link Collections#emptySet()}.
+     */
+    public static Set<ComponentName> getEnabledServicesFromSettings(Context context, int userId) {
+        final String enabledServicesSetting = Settings.Secure.getStringForUser(
+                context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+                userId);
+        if (TextUtils.isEmpty(enabledServicesSetting)) {
+            return Collections.emptySet();
+        }
+
+        final Set<ComponentName> enabledServices = new HashSet<>();
+        final TextUtils.StringSplitter colonSplitter =
+                new TextUtils.SimpleStringSplitter(SERVICES_SEPARATOR);
+        colonSplitter.setString(enabledServicesSetting);
+
+        for (String componentNameString : colonSplitter) {
+            final ComponentName enabledService = ComponentName.unflattenFromString(
+                    componentNameString);
+            if (enabledService != null) {
+                enabledServices.add(enabledService);
+            }
+        }
+
+        return enabledServices;
+    }
+
+    /**
+     * Changes an accessibility component's state.
+     */
+    public static void setAccessibilityServiceState(Context context, ComponentName componentName,
+            boolean enabled) {
+        setAccessibilityServiceState(context, componentName, enabled, UserHandle.myUserId());
+    }
+
+    /**
+     * Changes an accessibility component's state for {@param userId}.
+     */
+    public static void setAccessibilityServiceState(Context context, ComponentName componentName,
+            boolean enabled, int userId) {
+        Set<ComponentName> enabledServices = getEnabledServicesFromSettings(
+                context, userId);
+
+        if (enabledServices.isEmpty()) {
+            enabledServices = new ArraySet<>(/* capacity= */ 1);
+        }
+
+        if (enabled) {
+            enabledServices.add(componentName);
+        } else {
+            enabledServices.remove(componentName);
+        }
+
+        final StringBuilder enabledServicesBuilder = new StringBuilder();
+        for (ComponentName enabledService : enabledServices) {
+            enabledServicesBuilder.append(enabledService.flattenToString());
+            enabledServicesBuilder.append(
+                    SERVICES_SEPARATOR);
+        }
+
+        final int enabledServicesBuilderLength = enabledServicesBuilder.length();
+        if (enabledServicesBuilderLength > 0) {
+            enabledServicesBuilder.deleteCharAt(enabledServicesBuilderLength - 1);
+        }
+
+        Settings.Secure.putStringForUser(context.getContentResolver(),
+                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+                enabledServicesBuilder.toString(), userId);
+    }
+
+    /**
+     * Gets the corresponding fragment type of a given accessibility service.
+     *
+     * @param accessibilityServiceInfo The accessibilityService's info.
+     * @return int from {@link AccessibilityServiceFragmentType}.
+     */
+    public static @AccessibilityServiceFragmentType int getAccessibilityServiceFragmentType(
+            AccessibilityServiceInfo accessibilityServiceInfo) {
+        final int targetSdk = accessibilityServiceInfo.getResolveInfo()
+                .serviceInfo.applicationInfo.targetSdkVersion;
+        final boolean requestA11yButton = (accessibilityServiceInfo.flags
+                & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0;
+
+        if (targetSdk <= Build.VERSION_CODES.Q) {
+            return AccessibilityServiceFragmentType.LEGACY;
+        }
+        return requestA11yButton
+                ? AccessibilityServiceFragmentType.INVISIBLE
+                : AccessibilityServiceFragmentType.INTUITIVE;
+    }
+}
diff --git a/core/java/com/android/internal/accessibility/util/ShortcutUtils.java b/core/java/com/android/internal/accessibility/util/ShortcutUtils.java
new file mode 100644
index 0000000..7df712f
--- /dev/null
+++ b/core/java/com/android/internal/accessibility/util/ShortcutUtils.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.accessibility.util;
+import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_BUTTON;
+import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY;
+
+import static com.android.internal.accessibility.common.ShortcutConstants.SERVICES_SEPARATOR;
+import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.view.accessibility.AccessibilityManager.ShortcutType;
+
+import java.util.StringJoiner;
+
+/**
+ * Collection of utilities for accessibility shortcut.
+ */
+public final class ShortcutUtils {
+    private ShortcutUtils() {}
+
+    private static final TextUtils.SimpleStringSplitter sStringColonSplitter =
+            new TextUtils.SimpleStringSplitter(SERVICES_SEPARATOR);
+
+    /**
+     * Opts out component name into colon-separated {@code shortcutType} key's string in Settings.
+     *
+     * @param context The current context.
+     * @param shortcutType The preferred shortcut type user selected.
+     * @param componentId The component id that need to be opted out from Settings.
+     */
+    public static void optOutValueFromSettings(
+            Context context, @UserShortcutType int shortcutType, String componentId) {
+        final StringJoiner joiner = new StringJoiner(String.valueOf(SERVICES_SEPARATOR));
+        final String targetsKey = convertToKey(shortcutType);
+        final String targetsValue = Settings.Secure.getString(context.getContentResolver(),
+                targetsKey);
+
+        if (TextUtils.isEmpty(targetsValue)) {
+            return;
+        }
+
+        sStringColonSplitter.setString(targetsValue);
+        while (sStringColonSplitter.hasNext()) {
+            final String id = sStringColonSplitter.next();
+            if (TextUtils.isEmpty(id) || componentId.equals(id)) {
+                continue;
+            }
+            joiner.add(id);
+        }
+
+        Settings.Secure.putString(context.getContentResolver(), targetsKey, joiner.toString());
+    }
+
+    /**
+     * Returns if component name existed in one of {@code shortcutTypes} string in Settings.
+     *
+     * @param context The current context.
+     * @param shortcutTypes A combination of {@link UserShortcutType}.
+     * @param componentId The component name that need to be checked existed in Settings.
+     * @return {@code true} if componentName existed in Settings.
+     */
+    public static boolean hasValuesInSettings(Context context, int shortcutTypes,
+            @NonNull String componentId) {
+        boolean exist = false;
+        if ((shortcutTypes & UserShortcutType.SOFTWARE) == UserShortcutType.SOFTWARE) {
+            exist = hasValueInSettings(context, UserShortcutType.SOFTWARE, componentId);
+        }
+        if (((shortcutTypes & UserShortcutType.HARDWARE) == UserShortcutType.HARDWARE)) {
+            exist |= hasValueInSettings(context, UserShortcutType.HARDWARE, componentId);
+        }
+        return exist;
+    }
+
+
+    /**
+     * Returns if component name existed in Settings.
+     *
+     * @param context The current context.
+     * @param shortcutType The preferred shortcut type user selected.
+     * @param componentId The component id that need to be checked existed in Settings.
+     * @return {@code true} if componentName existed in Settings.
+     */
+    public static boolean hasValueInSettings(Context context, @UserShortcutType int shortcutType,
+            @NonNull String componentId) {
+        final String targetKey = convertToKey(shortcutType);
+        final String targetString = Settings.Secure.getString(context.getContentResolver(),
+                targetKey);
+
+        if (TextUtils.isEmpty(targetString)) {
+            return false;
+        }
+
+        sStringColonSplitter.setString(targetString);
+        while (sStringColonSplitter.hasNext()) {
+            final String id = sStringColonSplitter.next();
+            if (componentId.equals(id)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Converts {@link UserShortcutType} to key in Settings.
+     *
+     * @param type The shortcut type.
+     * @return Mapping key in Settings.
+     */
+    public static String convertToKey(@UserShortcutType int type) {
+        switch (type) {
+            case UserShortcutType.SOFTWARE:
+                return Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT;
+            case UserShortcutType.HARDWARE:
+                return Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE;
+            case UserShortcutType.TRIPLETAP:
+                return Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED;
+            default:
+                throw new IllegalArgumentException(
+                        "Unsupported user shortcut type: " + type);
+        }
+    }
+
+    /**
+     * Converts {@link ShortcutType} to {@link UserShortcutType}.
+     *
+     * @param type The shortcut type.
+     * @return {@link UserShortcutType}.
+     */
+    public static @UserShortcutType int convertToUserType(@ShortcutType int type) {
+        switch (type) {
+            case ACCESSIBILITY_BUTTON:
+                return UserShortcutType.SOFTWARE;
+            case ACCESSIBILITY_SHORTCUT_KEY:
+                return UserShortcutType.HARDWARE;
+            default:
+                throw new IllegalArgumentException(
+                        "Unsupported shortcut type:" + type);
+        }
+    }
+}
diff --git a/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java b/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java
index 86d2ed6..852deb2 100644
--- a/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java
+++ b/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java
@@ -22,16 +22,25 @@
 import static com.android.internal.accessibility.AccessibilityShortcutController.COLOR_INVERSION_COMPONENT_NAME;
 import static com.android.internal.accessibility.AccessibilityShortcutController.DALTONIZER_COMPONENT_NAME;
 import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
-import static com.android.internal.app.AccessibilityButtonChooserActivity.WhiteListingFeatureElementIndex.COMPONENT_ID;
-import static com.android.internal.app.AccessibilityButtonChooserActivity.WhiteListingFeatureElementIndex.FRAGMENT_TYPE;
-import static com.android.internal.app.AccessibilityButtonChooserActivity.WhiteListingFeatureElementIndex.ICON_ID;
-import static com.android.internal.app.AccessibilityButtonChooserActivity.WhiteListingFeatureElementIndex.LABEL_ID;
-import static com.android.internal.app.AccessibilityButtonChooserActivity.WhiteListingFeatureElementIndex.SETTINGS_KEY;
+import static com.android.internal.accessibility.common.ShortcutConstants.AccessibilityServiceFragmentType;
+import static com.android.internal.accessibility.common.ShortcutConstants.DISABLED_ALPHA;
+import static com.android.internal.accessibility.common.ShortcutConstants.ENABLED_ALPHA;
+import static com.android.internal.accessibility.common.ShortcutConstants.ShortcutMenuMode;
+import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType;
+import static com.android.internal.accessibility.common.ShortcutConstants.WhiteListingFeatureElementIndex.COMPONENT_ID;
+import static com.android.internal.accessibility.common.ShortcutConstants.WhiteListingFeatureElementIndex.FRAGMENT_TYPE;
+import static com.android.internal.accessibility.common.ShortcutConstants.WhiteListingFeatureElementIndex.ICON_ID;
+import static com.android.internal.accessibility.common.ShortcutConstants.WhiteListingFeatureElementIndex.LABEL_ID;
+import static com.android.internal.accessibility.common.ShortcutConstants.WhiteListingFeatureElementIndex.SETTINGS_KEY;
+import static com.android.internal.accessibility.util.AccessibilityUtils.getAccessibilityServiceFragmentType;
+import static com.android.internal.accessibility.util.AccessibilityUtils.setAccessibilityServiceState;
+import static com.android.internal.accessibility.util.ShortcutUtils.convertToUserType;
+import static com.android.internal.accessibility.util.ShortcutUtils.hasValuesInSettings;
+import static com.android.internal.accessibility.util.ShortcutUtils.optOutValueFromSettings;
 import static com.android.internal.util.Preconditions.checkArgument;
 
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.accessibilityservice.AccessibilityShortcutInfo;
-import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.Activity;
@@ -44,12 +53,8 @@
 import android.graphics.ColorMatrix;
 import android.graphics.ColorMatrixColorFilter;
 import android.graphics.drawable.Drawable;
-import android.os.Build;
 import android.os.Bundle;
-import android.os.UserHandle;
 import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.ArraySet;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -64,24 +69,14 @@
 
 import com.android.internal.R;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
-import java.util.StringJoiner;
 
 /**
  * Activity used to display and persist a service or feature target for the Accessibility button.
  */
 public class AccessibilityButtonChooserActivity extends Activity {
-    private static final char SERVICES_SEPARATOR = ':';
-    private static final float DISABLED_ALPHA = 0.5f;
-    private static final float ENABLED_ALPHA = 1.0f;
-    private static final TextUtils.SimpleStringSplitter sStringColonSplitter =
-            new TextUtils.SimpleStringSplitter(SERVICES_SEPARATOR);
     @ShortcutType
     private int mShortcutType;
     @UserShortcutType
@@ -90,97 +85,6 @@
     private AlertDialog mAlertDialog;
     private TargetAdapter mTargetAdapter;
 
-    /**
-     * Annotation for different user shortcut type UI type.
-     *
-     * {@code DEFAULT} for displaying default value.
-     * {@code SOFTWARE} for displaying specifying the accessibility services or features which
-     * choose accessibility button in the navigation bar as preferred shortcut.
-     * {@code HARDWARE} for displaying specifying the accessibility services or features which
-     * choose accessibility shortcut as preferred shortcut.
-     * {@code TRIPLETAP} for displaying specifying magnification to be toggled via quickly
-     * tapping screen 3 times as preferred shortcut.
-     */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({
-            UserShortcutType.DEFAULT,
-            UserShortcutType.SOFTWARE,
-            UserShortcutType.HARDWARE,
-            UserShortcutType.TRIPLETAP,
-    })
-    /** Denotes the user shortcut type. */
-    private @interface UserShortcutType {
-        int DEFAULT = 0;
-        int SOFTWARE = 1; // 1 << 0
-        int HARDWARE = 2; // 1 << 1
-        int TRIPLETAP = 4; // 1 << 2
-    }
-
-    /**
-     * Annotation for different accessibilityService fragment UI type.
-     *
-     * {@code LEGACY} for displaying appearance aligned with sdk version Q accessibility service
-     * page, but only hardware shortcut allowed and under service in version Q or early.
-     * {@code INVISIBLE} for displaying appearance without switch bar.
-     * {@code INTUITIVE} for displaying appearance with version R accessibility design.
-     * {@code BOUNCE} for displaying appearance with pop-up action.
-     */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({
-            AccessibilityServiceFragmentType.LEGACY,
-            AccessibilityServiceFragmentType.INVISIBLE,
-            AccessibilityServiceFragmentType.INTUITIVE,
-            AccessibilityServiceFragmentType.BOUNCE,
-    })
-    private @interface AccessibilityServiceFragmentType {
-        int LEGACY = 0;
-        int INVISIBLE = 1;
-        int INTUITIVE = 2;
-        int BOUNCE = 3;
-    }
-
-    /**
-     * Annotation for different shortcut menu mode.
-     *
-     * {@code LAUNCH} for clicking list item to trigger the service callback.
-     * {@code EDIT} for clicking list item and save button to disable the service.
-     */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({
-            ShortcutMenuMode.LAUNCH,
-            ShortcutMenuMode.EDIT,
-    })
-    private @interface ShortcutMenuMode {
-        int LAUNCH = 0;
-        int EDIT = 1;
-    }
-
-    /**
-     * Annotation for align the element index of white listing feature
-     * {@code WHITE_LISTING_FEATURES}.
-     *
-     * {@code COMPONENT_ID} is to get the service component name.
-     * {@code LABEL_ID} is to get the service label text.
-     * {@code ICON_ID} is to get the service icon.
-     * {@code FRAGMENT_TYPE} is to get the service fragment type.
-     * {@code SETTINGS_KEY} is to get the service settings key.
-     */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({
-            WhiteListingFeatureElementIndex.COMPONENT_ID,
-            WhiteListingFeatureElementIndex.LABEL_ID,
-            WhiteListingFeatureElementIndex.ICON_ID,
-            WhiteListingFeatureElementIndex.FRAGMENT_TYPE,
-            WhiteListingFeatureElementIndex.SETTINGS_KEY,
-    })
-    @interface WhiteListingFeatureElementIndex {
-        int COMPONENT_ID = 0;
-        int LABEL_ID = 1;
-        int ICON_ID = 2;
-        int FRAGMENT_TYPE = 3;
-        int SETTINGS_KEY = 4;
-    }
-
     private static final String[][] WHITE_LISTING_FEATURES = {
             {
                     COLOR_INVERSION_COMPONENT_NAME.flattenToString(),
@@ -224,8 +128,11 @@
 
         mTargets.addAll(getServiceTargets(this, mShortcutType));
 
+        final String selectDialogTitle =
+                getString(R.string.accessibility_select_shortcut_menu_title);
         mTargetAdapter = new TargetAdapter(mTargets, mShortcutType);
         mAlertDialog = new AlertDialog.Builder(this)
+                .setTitle(selectDialogTitle)
                 .setAdapter(mTargetAdapter, /* listener= */ null)
                 .setPositiveButton(
                         getString(R.string.edit_accessibility_shortcut_menu_button),
@@ -242,27 +149,6 @@
         super.onDestroy();
     }
 
-    /**
-     * Gets the corresponding fragment type of a given accessibility service.
-     *
-     * @param accessibilityServiceInfo The accessibilityService's info.
-     * @return int from {@link AccessibilityServiceFragmentType}.
-     */
-    private static @AccessibilityServiceFragmentType int getAccessibilityServiceFragmentType(
-            AccessibilityServiceInfo accessibilityServiceInfo) {
-        final int targetSdk = accessibilityServiceInfo.getResolveInfo()
-                .serviceInfo.applicationInfo.targetSdkVersion;
-        final boolean requestA11yButton = (accessibilityServiceInfo.flags
-                & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0;
-
-        if (targetSdk <= Build.VERSION_CODES.Q) {
-            return AccessibilityServiceFragmentType.LEGACY;
-        }
-        return requestA11yButton
-                ? AccessibilityServiceFragmentType.INVISIBLE
-                : AccessibilityServiceFragmentType.INTUITIVE;
-    }
-
     private static List<AccessibilityButtonTarget> getServiceTargets(@NonNull Context context,
             @ShortcutType int shortcutType) {
         final List<AccessibilityButtonTarget> targets = new ArrayList<>();
@@ -761,193 +647,17 @@
     private void updateDialogListeners() {
         final boolean isEditMenuMode =
                 (mTargetAdapter.getShortcutMenuMode() == ShortcutMenuMode.EDIT);
+        final int selectDialogTitleId = R.string.accessibility_select_shortcut_menu_title;
+        final int editDialogTitleId =
+                (mShortcutType == ACCESSIBILITY_BUTTON)
+                        ? R.string.accessibility_edit_shortcut_menu_button_title
+                        : R.string.accessibility_edit_shortcut_menu_volume_title;
+
+        mAlertDialog.setTitle(getString(isEditMenuMode ? editDialogTitleId : selectDialogTitleId));
 
         mAlertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(
                 isEditMenuMode ? view -> onCancelButtonClicked() : view -> onEditButtonClicked());
         mAlertDialog.getListView().setOnItemClickListener(
                 isEditMenuMode ? this::onTargetDeleted : this::onTargetSelected);
     }
-
-    /**
-     * @return the set of enabled accessibility services for {@param userId}. If there are no
-     * services, it returns the unmodifiable {@link Collections#emptySet()}.
-     */
-    private Set<ComponentName> getEnabledServicesFromSettings(Context context, int userId) {
-        final String enabledServicesSetting = Settings.Secure.getStringForUser(
-                context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
-                userId);
-        if (TextUtils.isEmpty(enabledServicesSetting)) {
-            return Collections.emptySet();
-        }
-
-        final Set<ComponentName> enabledServices = new HashSet<>();
-        final TextUtils.StringSplitter colonSplitter =
-                new TextUtils.SimpleStringSplitter(SERVICES_SEPARATOR);
-        colonSplitter.setString(enabledServicesSetting);
-
-        for (String componentNameString : colonSplitter) {
-            final ComponentName enabledService = ComponentName.unflattenFromString(
-                    componentNameString);
-            if (enabledService != null) {
-                enabledServices.add(enabledService);
-            }
-        }
-
-        return enabledServices;
-    }
-
-    /**
-     * Changes an accessibility component's state.
-     */
-    private void setAccessibilityServiceState(Context context, ComponentName componentName,
-            boolean enabled) {
-        setAccessibilityServiceState(context, componentName, enabled, UserHandle.myUserId());
-    }
-
-    /**
-     * Changes an accessibility component's state for {@param userId}.
-     */
-    private void setAccessibilityServiceState(Context context, ComponentName componentName,
-            boolean enabled, int userId) {
-        Set<ComponentName> enabledServices = getEnabledServicesFromSettings(
-                context, userId);
-
-        if (enabledServices.isEmpty()) {
-            enabledServices = new ArraySet<>(/* capacity= */ 1);
-        }
-
-        if (enabled) {
-            enabledServices.add(componentName);
-        } else {
-            enabledServices.remove(componentName);
-        }
-
-        final StringBuilder enabledServicesBuilder = new StringBuilder();
-        for (ComponentName enabledService : enabledServices) {
-            enabledServicesBuilder.append(enabledService.flattenToString());
-            enabledServicesBuilder.append(
-                    SERVICES_SEPARATOR);
-        }
-
-        final int enabledServicesBuilderLength = enabledServicesBuilder.length();
-        if (enabledServicesBuilderLength > 0) {
-            enabledServicesBuilder.deleteCharAt(enabledServicesBuilderLength - 1);
-        }
-
-        Settings.Secure.putStringForUser(context.getContentResolver(),
-                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
-                enabledServicesBuilder.toString(), userId);
-    }
-
-    /**
-     * Opts out component name into colon-separated {@code shortcutType} key's string in Settings.
-     *
-     * @param context The current context.
-     * @param shortcutType The preferred shortcut type user selected.
-     * @param componentId The component id that need to be opted out from Settings.
-     */
-    private void optOutValueFromSettings(
-            Context context, @UserShortcutType int shortcutType, String componentId) {
-        final StringJoiner joiner = new StringJoiner(String.valueOf(SERVICES_SEPARATOR));
-        final String targetsKey = convertToKey(shortcutType);
-        final String targetsValue = Settings.Secure.getString(context.getContentResolver(),
-                targetsKey);
-
-        if (TextUtils.isEmpty(targetsValue)) {
-            return;
-        }
-
-        sStringColonSplitter.setString(targetsValue);
-        while (sStringColonSplitter.hasNext()) {
-            final String id = sStringColonSplitter.next();
-            if (TextUtils.isEmpty(id) || componentId.equals(id)) {
-                continue;
-            }
-            joiner.add(id);
-        }
-
-        Settings.Secure.putString(context.getContentResolver(), targetsKey, joiner.toString());
-    }
-
-    /**
-     * Returns if component name existed in one of {@code shortcutTypes} string in Settings.
-     *
-     * @param context The current context.
-     * @param shortcutTypes A combination of {@link UserShortcutType}.
-     * @param componentId The component name that need to be checked existed in Settings.
-     * @return {@code true} if componentName existed in Settings.
-     */
-    private boolean hasValuesInSettings(Context context, int shortcutTypes,
-            @NonNull String componentId) {
-        boolean exist = false;
-        if ((shortcutTypes & UserShortcutType.SOFTWARE) == UserShortcutType.SOFTWARE) {
-            exist = hasValueInSettings(context, UserShortcutType.SOFTWARE, componentId);
-        }
-        if (((shortcutTypes & UserShortcutType.HARDWARE) == UserShortcutType.HARDWARE)) {
-            exist |= hasValueInSettings(context, UserShortcutType.HARDWARE, componentId);
-        }
-        return exist;
-    }
-
-
-    /**
-     * Returns if component name existed in Settings.
-     *
-     * @param context The current context.
-     * @param shortcutType The preferred shortcut type user selected.
-     * @param componentId The component id that need to be checked existed in Settings.
-     * @return {@code true} if componentName existed in Settings.
-     */
-    private boolean hasValueInSettings(Context context, @UserShortcutType int shortcutType,
-            @NonNull String componentId) {
-        final String targetKey = convertToKey(shortcutType);
-        final String targetString = Settings.Secure.getString(context.getContentResolver(),
-                targetKey);
-
-        if (TextUtils.isEmpty(targetString)) {
-            return false;
-        }
-
-        sStringColonSplitter.setString(targetString);
-        while (sStringColonSplitter.hasNext()) {
-            final String id = sStringColonSplitter.next();
-            if (componentId.equals(id)) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    /**
-     * Converts {@link UserShortcutType} to key in Settings.
-     *
-     * @param type The shortcut type.
-     * @return Mapping key in Settings.
-     */
-    private String convertToKey(@UserShortcutType int type) {
-        switch (type) {
-            case UserShortcutType.SOFTWARE:
-                return Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT;
-            case UserShortcutType.HARDWARE:
-                return Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE;
-            case UserShortcutType.TRIPLETAP:
-                return Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED;
-            default:
-                throw new IllegalArgumentException(
-                        "Unsupported user shortcut type: " + type);
-        }
-    }
-
-    private static @UserShortcutType int convertToUserType(@ShortcutType int type) {
-        switch (type) {
-            case ACCESSIBILITY_BUTTON:
-                return UserShortcutType.SOFTWARE;
-            case ACCESSIBILITY_SHORTCUT_KEY:
-                return UserShortcutType.HARDWARE;
-            default:
-                throw new IllegalArgumentException(
-                        "Unsupported shortcut type:" + type);
-        }
-    }
 }
diff --git a/core/java/com/android/internal/content/om/OverlayConfig.java b/core/java/com/android/internal/content/om/OverlayConfig.java
index 2b08a77..fbef027 100644
--- a/core/java/com/android/internal/content/om/OverlayConfig.java
+++ b/core/java/com/android/internal/content/om/OverlayConfig.java
@@ -21,7 +21,6 @@
 import android.content.pm.PackagePartitions;
 import android.content.pm.parsing.ParsingPackageRead;
 import android.os.Build;
-import android.os.Process;
 import android.os.Trace;
 import android.util.ArrayMap;
 import android.util.Log;
@@ -186,13 +185,6 @@
      */
     @NonNull
     public static OverlayConfig getZygoteInstance() {
-        if (Process.myUid() != Process.ROOT_UID) {
-            // Scan the overlays in the zygote process to generate configuration settings for
-            // overlays on the system image. Do not cache this instance so OverlayConfig will not
-            // be present in applications by default.
-            throw new IllegalStateException("Can only be invoked in the root process");
-        }
-
         Trace.traceBegin(Trace.TRACE_TAG_RRO, "OverlayConfig#getZygoteInstance");
         try {
             return new OverlayConfig(null /* rootDirectory */, OverlayScanner::new,
@@ -209,13 +201,12 @@
      */
     @NonNull
     public static OverlayConfig initializeSystemInstance(PackageProvider packageProvider) {
-        if (Process.myUid() != Process.SYSTEM_UID) {
-            throw new IllegalStateException("Can only be invoked in the system process");
-        }
-
         Trace.traceBegin(Trace.TRACE_TAG_RRO, "OverlayConfig#initializeSystemInstance");
-        sInstance = new OverlayConfig(null, null, packageProvider);
-        Trace.traceEnd(Trace.TRACE_TAG_RRO);
+        try {
+            sInstance = new OverlayConfig(null, null, packageProvider);
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_RRO);
+        }
         return sInstance;
     }
 
@@ -379,10 +370,6 @@
      */
     @NonNull
     public String[] createImmutableFrameworkIdmapsInZygote() {
-        if (Process.myUid() != Process.ROOT_UID) {
-            throw new IllegalStateException("This method can only be called from the root process");
-        }
-
         final String targetPath = "/system/framework/framework-res.apk";
         final ArrayList<String> idmapPaths = new ArrayList<>();
         final ArrayList<IdmapInvocation> idmapInvocations =
diff --git a/core/res/res/layout/accessibility_button_chooser_item.xml b/core/res/res/layout/accessibility_button_chooser_item.xml
index d19e313..c01766b 100644
--- a/core/res/res/layout/accessibility_button_chooser_item.xml
+++ b/core/res/res/layout/accessibility_button_chooser_item.xml
@@ -38,7 +38,9 @@
         android:layout_height="wrap_content"
         android:layout_marginStart="14dp"
         android:layout_weight="1"
-        android:textColor="?attr/textColorPrimary"/>
+        android:textSize="20sp"
+        android:textColor="?attr/textColorPrimary"
+        android:fontFamily="sans-serif-medium"/>
 
     <FrameLayout
         android:id="@+id/accessibility_button_target_item_container"
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index d83236c..2356b17 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4403,6 +4403,21 @@
         accessibility feature.
     </string>
 
+    <!-- Title for accessibility select shortcut menu dialog. [CHAR LIMIT=100] -->
+    <string name="accessibility_select_shortcut_menu_title">Tap the accessibility app you want to use</string>
+
+    <!-- Title for accessibility edit shortcut selection menu dialog, and dialog is triggered
+    from accessibility button. [CHAR LIMIT=100] -->
+    <string name="accessibility_edit_shortcut_menu_button_title">Choose apps you want to use with
+        accessibility button
+    </string>
+
+    <!-- Title for accessibility edit shortcut selection menu dialog, and dialog is triggered
+    from volume key shortcut. [CHAR LIMIT=100] -->
+    <string name="accessibility_edit_shortcut_menu_volume_title">Choose apps you want to use with
+        volume key shortcut
+    </string>
+
     <!-- Text in button that edit the accessibility shortcut menu, user can delete
     any service item in the menu list. [CHAR LIMIT=100] -->
     <string name="edit_accessibility_shortcut_menu_button">Edit shortcuts</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index f3174d3..92e7fcd 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3237,6 +3237,10 @@
   <java-symbol type="string" name="config_defaultAccessibilityService" />
   <java-symbol type="string" name="accessibility_shortcut_spoken_feedback" />
 
+  <java-symbol type="string" name="accessibility_select_shortcut_menu_title" />
+  <java-symbol type="string" name="accessibility_edit_shortcut_menu_button_title" />
+  <java-symbol type="string" name="accessibility_edit_shortcut_menu_volume_title" />
+
   <!-- Accessibility Button -->
   <java-symbol type="layout" name="accessibility_button_chooser_item" />
   <java-symbol type="id" name="accessibility_button_target_icon" />
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
index 60c1a94..1ae3d4f 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
@@ -225,8 +225,8 @@
      */
     Rect getDestinationBounds(float aspectRatio, Rect bounds) {
         final Rect destinationBounds;
+        final Rect defaultBounds = getDefaultBounds(mReentrySnapFraction, mReentrySize);
         if (bounds == null) {
-            final Rect defaultBounds = getDefaultBounds(mReentrySnapFraction, mReentrySize);
             destinationBounds = new Rect(defaultBounds);
         } else {
             destinationBounds = new Rect(bounds);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index 6b3b748..8ada3c3 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -168,7 +168,7 @@
                 // bounds. We want to restore to the unexpanded bounds when re-entering pip,
                 // so we save the bounds before expansion (normal) instead of the current
                 // bounds.
-                mReentryBounds.set(mTouchHandler.getMinBounds());
+                mReentryBounds.set(mTouchHandler.getNormalBounds());
                 // Apply the snap fraction of the current bounds to the normal bounds.
                 float snapFraction = mPipBoundsHandler.getSnapFraction(bounds);
                 mPipBoundsHandler.applySnapFraction(mReentryBounds, snapFraction);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java
index 5926b89..8fff419 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java
@@ -65,7 +65,6 @@
     private final PointF mDownPoint = new PointF();
     private final Point mMaxSize = new Point();
     private final Point mMinSize = new Point();
-    private final Rect mLastResizeBounds = new Rect();
     private final Rect mTmpBounds = new Rect();
     private final int mDelta;
 
@@ -194,7 +193,11 @@
             }
 
         } else if (mAllowGesture) {
-
+            final Rect currentPipBounds = mMotionHelper.getBounds();
+            Rect newSize = TaskResizingAlgorithm.resizeDrag(ev.getX(), ev.getY(), mDownPoint.x,
+                    mDownPoint.y, currentPipBounds, mCtrlType, mMinSize.x, mMinSize.y, mMaxSize,
+                    true, true);
+            mPipBoundsHandler.transformBoundsToAspectRatio(newSize);
             switch (action) {
                 case MotionEvent.ACTION_POINTER_DOWN:
                     // We do not support multi touch for resizing via drag
@@ -203,18 +206,12 @@
                 case MotionEvent.ACTION_MOVE:
                     // Capture inputs
                     mInputMonitor.pilferPointers();
-                    final Rect currentPipBounds = mMotionHelper.getBounds();
-                    mLastResizeBounds.set(TaskResizingAlgorithm.resizeDrag(ev.getX(), ev.getY(),
-                            mDownPoint.x, mDownPoint.y, currentPipBounds, mCtrlType, mMinSize.x,
-                            mMinSize.y, mMaxSize, true, true));
-                    mPipBoundsHandler.transformBoundsToAspectRatio(mLastResizeBounds);
-                    mPipTaskOrganizer.resizePip(mLastResizeBounds);
-
+                    //TODO: Actually do resize here.
                     break;
                 case MotionEvent.ACTION_UP:
                 case MotionEvent.ACTION_CANCEL:
-                    mPipTaskOrganizer.finishResize(mLastResizeBounds);
-                    mLastResizeBounds.setEmpty();
+                    //TODO: Finish resize operation here.
+                    mMotionHelper.synchronizePinnedStackBounds();
                     mCtrlType = CTRL_NONE;
                     mAllowGesture = false;
                     break;
@@ -226,7 +223,7 @@
         mMaxSize.set(maxX, maxY);
     }
 
-    void updateMinSize(int minX, int minY) {
+    void updateMiniSize(int minX, int minY) {
         mMinSize.set(minX, minY);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index bd22480..c3212b8 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -41,7 +41,6 @@
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityWindowInfo;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.logging.MetricsLoggerWrapper;
 import com.android.systemui.R;
 import com.android.systemui.pip.PipBoundsHandler;
@@ -74,7 +73,7 @@
     private final Context mContext;
     private final IActivityManager mActivityManager;
     private final PipBoundsHandler mPipBoundsHandler;
-    private PipResizeGestureHandler mPipResizeGestureHandler;
+    private final PipResizeGestureHandler mPipResizeGestureHandler;
     private IPinnedStackController mPinnedStackController;
 
     private final PipMenuActivityController mMenuController;
@@ -85,22 +84,14 @@
 
     // The current movement bounds
     private Rect mMovementBounds = new Rect();
-    // The current resized bounds, changed by user resize.
-    // Note that this is not necessarily the same as PipMotionHelper#getBounds, since it's possible
-    // that PIP is currently is in a expanded state (max size) but we still need mResizeBounds to
-    // know what size to restore to once expand animation times out.
-    @VisibleForTesting Rect mResizedBounds = new Rect();
 
     // The reference inset bounds, used to determine the dismiss fraction
     private Rect mInsetBounds = new Rect();
-
-    // The reference bounds used to calculate the minimum/maximum target bounds
-    // The bound in which PIP enters is the starting/minimum bound, while the expanded/auto-resized
-    // bound is the maximum bound.
-    private Rect mMinBounds = new Rect();
-    @VisibleForTesting Rect mMinMovementBounds = new Rect();
-    private Rect mMaxBounds = new Rect();
-    @VisibleForTesting Rect mMaxMovementBounds = new Rect();
+    // The reference bounds used to calculate the normal/expanded target bounds
+    private Rect mNormalBounds = new Rect();
+    private Rect mNormalMovementBounds = new Rect();
+    private Rect mExpandedBounds = new Rect();
+    private Rect mExpandedMovementBounds = new Rect();
     private int mExpandedShortestEdgeSize;
 
     // Used to workaround an issue where the WM rotation happens before we are notified, allowing
@@ -135,7 +126,7 @@
     private final PipTouchState mTouchState;
     private final FlingAnimationUtils mFlingAnimationUtils;
     private final FloatingContentCoordinator mFloatingContentCoordinator;
-    private PipMotionHelper mMotionHelper;
+    private final PipMotionHelper mMotionHelper;
     private PipTouchGesture mGesture;
 
     // Temp vars
@@ -244,16 +235,14 @@
 
             mFloatingContentCoordinator.onContentRemoved(mMotionHelper);
         }
-        mResizedBounds.setEmpty();
         mPipResizeGestureHandler.onActivityUnpinned();
     }
 
     public void onPinnedStackAnimationEnded() {
         // Always synchronize the motion helper bounds once PiP animations finish
         mMotionHelper.synchronizePinnedStackBounds();
-
-        updateMovementBounds();
-        mResizedBounds.set(mMinBounds);
+        mPipResizeGestureHandler.updateMiniSize(mMotionHelper.getBounds().width(),
+                mMotionHelper.getBounds().height());
 
         if (mShowPipMenuOnAnimationEnd) {
             mMenuController.showMenu(MENU_STATE_CLOSE, mMotionHelper.getBounds(),
@@ -277,10 +266,7 @@
         mShelfHeight = shelfHeight;
     }
 
-    /**
-     * Update all the cached bounds (movement, min, max, etc.)
-     */
-    public void onMovementBoundsChanged(Rect insetBounds, Rect minBounds, Rect curBounds,
+    public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds, Rect curBounds,
             boolean fromImeAdjustment, boolean fromShelfAdjustment, int displayRotation) {
         final int bottomOffset = mIsImeShowing ? mImeHeight : 0;
         final boolean fromDisplayRotationChanged = (mDisplayRotation != displayRotation);
@@ -289,25 +275,23 @@
         }
 
         // Re-calculate the expanded bounds
-        mMinBounds.set(minBounds);
-        Rect minMovementBounds = new Rect();
-        mSnapAlgorithm.getMovementBounds(mMinBounds, insetBounds, minMovementBounds,
+        mNormalBounds = normalBounds;
+        Rect normalMovementBounds = new Rect();
+        mSnapAlgorithm.getMovementBounds(mNormalBounds, insetBounds, normalMovementBounds,
                 bottomOffset);
 
         // Calculate the expanded size
-        float aspectRatio = (float) minBounds.width() / minBounds.height();
+        float aspectRatio = (float) normalBounds.width() / normalBounds.height();
         Point displaySize = new Point();
         mContext.getDisplay().getRealSize(displaySize);
-        Size maxSize = mSnapAlgorithm.getSizeForAspectRatio(aspectRatio,
+        Size expandedSize = mSnapAlgorithm.getSizeForAspectRatio(aspectRatio,
                 mExpandedShortestEdgeSize, displaySize.x, displaySize.y);
-        mMaxBounds.set(0, 0, maxSize.getWidth(), maxSize.getHeight());
-        Rect maxMovementBounds = new Rect();
-        mSnapAlgorithm.getMovementBounds(mMaxBounds, insetBounds, maxMovementBounds,
+        mExpandedBounds.set(0, 0, expandedSize.getWidth(), expandedSize.getHeight());
+        mPipResizeGestureHandler.updateMaxSize(expandedSize.getWidth(), expandedSize.getHeight());
+        Rect expandedMovementBounds = new Rect();
+        mSnapAlgorithm.getMovementBounds(mExpandedBounds, insetBounds, expandedMovementBounds,
                 bottomOffset);
 
-        mPipResizeGestureHandler.updateMinSize(minBounds.width(), minBounds.height());
-        mPipResizeGestureHandler.updateMaxSize(mMaxBounds.width(), mMaxBounds.height());
-
         // The extra offset does not really affect the movement bounds, but are applied based on the
         // current state (ime showing, or shelf offset) when we need to actually shift
         int extraOffset = Math.max(
@@ -324,8 +308,8 @@
                 final float offsetBufferPx = BOTTOM_OFFSET_BUFFER_DP
                         * mContext.getResources().getDisplayMetrics().density;
                 final Rect toMovementBounds = mMenuState == MENU_STATE_FULL && willResizeMenu()
-                        ? new Rect(maxMovementBounds)
-                        : new Rect(minMovementBounds);
+                        ? new Rect(expandedMovementBounds)
+                        : new Rect(normalMovementBounds);
                 final int prevBottom = mMovementBounds.bottom - mMovementBoundsExtraOffsets;
                 final int toBottom = toMovementBounds.bottom < toMovementBounds.top
                         ? toMovementBounds.bottom
@@ -339,17 +323,17 @@
 
         // Update the movement bounds after doing the calculations based on the old movement bounds
         // above
-        mMinMovementBounds = minMovementBounds;
-        mMaxMovementBounds = maxMovementBounds;
+        mNormalMovementBounds = normalMovementBounds;
+        mExpandedMovementBounds = expandedMovementBounds;
         mDisplayRotation = displayRotation;
         mInsetBounds.set(insetBounds);
-        updateMovementBounds();
+        updateMovementBounds(mMenuState);
         mMovementBoundsExtraOffsets = extraOffset;
 
         // If we have a deferred resize, apply it now
         if (mDeferResizeToNormalBoundsUntilRotation == displayRotation) {
-            mMotionHelper.animateToUnexpandedState(minBounds, mSavedSnapFraction,
-                    mMinMovementBounds, mMovementBounds, true /* immediate */);
+            mMotionHelper.animateToUnexpandedState(normalBounds, mSavedSnapFraction,
+                    mNormalMovementBounds, mMovementBounds, true /* immediate */);
             mSavedSnapFraction = -1f;
             mDeferResizeToNormalBoundsUntilRotation = -1;
         }
@@ -403,7 +387,7 @@
             case MotionEvent.ACTION_UP: {
                 // Update the movement bounds again if the state has changed since the user started
                 // dragging (ie. when the IME shows)
-                updateMovementBounds();
+                updateMovementBounds(mMenuState);
 
                 if (mGesture.onUp(mTouchState)) {
                     break;
@@ -501,13 +485,11 @@
         if (menuState == MENU_STATE_FULL && mMenuState != MENU_STATE_FULL) {
             // Save the current snap fraction and if we do not drag or move the PiP, then
             // we store back to this snap fraction.  Otherwise, we'll reset the snap
-            // fraction and snap to the closest edge.
-            // Also save the current resized bounds so when the menu disappears, we can restore it.
+            // fraction and snap to the closest edge
+            Rect expandedBounds = new Rect(mExpandedBounds);
             if (resize) {
-                mResizedBounds.set(mMotionHelper.getBounds());
-                Rect expandedBounds = new Rect(mMaxBounds);
                 mSavedSnapFraction = mMotionHelper.animateToExpandedState(expandedBounds,
-                        mMovementBounds, mMaxMovementBounds);
+                        mMovementBounds, mExpandedMovementBounds);
             }
         } else if (menuState == MENU_STATE_NONE && mMenuState == MENU_STATE_FULL) {
             // Try and restore the PiP to the closest edge, using the saved snap fraction
@@ -533,9 +515,9 @@
                 }
 
                 if (mDeferResizeToNormalBoundsUntilRotation == -1) {
-                    Rect normalBounds = new Rect(mResizedBounds);
+                    Rect normalBounds = new Rect(mNormalBounds);
                     mMotionHelper.animateToUnexpandedState(normalBounds, mSavedSnapFraction,
-                            mMinMovementBounds, mMovementBounds, false /* immediate */);
+                            mNormalMovementBounds, mMovementBounds, false /* immediate */);
                     mSavedSnapFraction = -1f;
                 }
             } else {
@@ -546,7 +528,7 @@
             }
         }
         mMenuState = menuState;
-        updateMovementBounds();
+        updateMovementBounds(menuState);
         // If pip menu has dismissed, we should register the A11y ActionReplacingConnection for pip
         // as well, or it can't handle a11y focus and pip menu can't perform any action.
         onRegistrationChanged(menuState == MENU_STATE_NONE);
@@ -562,26 +544,11 @@
         return mMotionHelper;
     }
 
-    @VisibleForTesting
-    PipResizeGestureHandler getPipResizeGestureHandler() {
-        return mPipResizeGestureHandler;
-    }
-
-    @VisibleForTesting
-    void setPipResizeGestureHandler(PipResizeGestureHandler pipResizeGestureHandler) {
-        mPipResizeGestureHandler = pipResizeGestureHandler;
-    }
-
-    @VisibleForTesting
-    void setPipMotionHelper(PipMotionHelper pipMotionHelper) {
-        mMotionHelper = pipMotionHelper;
-    }
-
     /**
      * @return the unexpanded bounds.
      */
-    public Rect getMinBounds() {
-        return mMinBounds;
+    public Rect getNormalBounds() {
+        return mNormalBounds;
     }
 
     /**
@@ -734,17 +701,17 @@
     };
 
     /**
-     * Updates the current movement bounds based on the current PIP size.
+     * Updates the current movement bounds based on whether the menu is currently visible and
+     * resized.
      */
-    private void updateMovementBounds() {
-        Rect movementBounds = new Rect();
-        mSnapAlgorithm.getMovementBounds(mMotionHelper.getBounds(), mInsetBounds,
-                movementBounds, mIsImeShowing ? mImeHeight : 0);
-        mMotionHelper.setCurrentMovementBounds(movementBounds);
-
-        boolean isMenuExpanded = mMenuState == MENU_STATE_FULL;
+    private void updateMovementBounds(int menuState) {
+        boolean isMenuExpanded = menuState == MENU_STATE_FULL;
+        mMovementBounds = isMenuExpanded && willResizeMenu()
+                ? mExpandedMovementBounds
+                : mNormalMovementBounds;
         mPipBoundsHandler.setMinEdgeSize(
-                isMenuExpanded  && willResizeMenu() ? mExpandedShortestEdgeSize : 0);
+                isMenuExpanded ? mExpandedShortestEdgeSize : 0);
+        mMotionHelper.setCurrentMovementBounds(mMovementBounds);
     }
 
     /**
@@ -762,18 +729,18 @@
         if (!mEnableResize) {
             return false;
         }
-        return mMaxBounds.width() != mMinBounds.width()
-                || mMaxBounds.height() != mMinBounds.height();
+        return mExpandedBounds.width() != mNormalBounds.width()
+                || mExpandedBounds.height() != mNormalBounds.height();
     }
 
     public void dump(PrintWriter pw, String prefix) {
         final String innerPrefix = prefix + "  ";
         pw.println(prefix + TAG);
         pw.println(innerPrefix + "mMovementBounds=" + mMovementBounds);
-        pw.println(innerPrefix + "mMinBounds=" + mMinBounds);
-        pw.println(innerPrefix + "mMinMovementBounds=" + mMinMovementBounds);
-        pw.println(innerPrefix + "mMaxBounds=" + mMaxBounds);
-        pw.println(innerPrefix + "mMaxMovementBounds=" + mMaxMovementBounds);
+        pw.println(innerPrefix + "mNormalBounds=" + mNormalBounds);
+        pw.println(innerPrefix + "mNormalMovementBounds=" + mNormalMovementBounds);
+        pw.println(innerPrefix + "mExpandedBounds=" + mExpandedBounds);
+        pw.println(innerPrefix + "mExpandedMovementBounds=" + mExpandedMovementBounds);
         pw.println(innerPrefix + "mMenuState=" + mMenuState);
         pw.println(innerPrefix + "mIsImeShowing=" + mIsImeShowing);
         pw.println(innerPrefix + "mImeHeight=" + mImeHeight);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipTouchHandlerTest.java
deleted file mode 100644
index 35abb14..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipTouchHandlerTest.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.pip.phone;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import android.app.IActivityManager;
-import android.app.IActivityTaskManager;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.util.Size;
-import android.view.DisplayInfo;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.pip.PipBoundsHandler;
-import com.android.systemui.pip.PipSnapAlgorithm;
-import com.android.systemui.pip.PipTaskOrganizer;
-import com.android.systemui.shared.system.InputConsumerController;
-import com.android.systemui.util.DeviceConfigProxy;
-import com.android.systemui.util.FloatingContentCoordinator;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-
-/**
- * Unit tests against {@link PipTouchHandler}, including but not limited to:
- * - Update movement bounds based on new bounds
- * - Update movement bounds based on IME/shelf
- * - Update movement bounds to PipResizeHandler
- */
-@RunWith(AndroidTestingRunner.class)
-@SmallTest
-@TestableLooper.RunWithLooper(setAsMainLooper = true)
-public class PipTouchHandlerTest extends SysuiTestCase {
-    private static final int ROUNDING_ERROR_MARGIN = 10;
-    private static final float DEFAULT_ASPECT_RATIO = 1f;
-    private static final Rect EMPTY_CURRENT_BOUNDS = null;
-
-    private PipTouchHandler mPipTouchHandler;
-    private DisplayInfo mDefaultDisplayInfo;
-
-    @Mock
-    private IActivityManager mActivityManager;
-
-    @Mock
-    private IActivityTaskManager mIActivityTaskManager;
-
-    @Mock
-    private PipMenuActivityController mPipMenuActivityController;
-
-    @Mock
-    private InputConsumerController mInputConsumerController;
-
-    @Mock
-    private PipBoundsHandler mPipBoundsHandler;
-
-    @Mock
-    private PipTaskOrganizer mPipTaskOrganizer;
-
-    @Mock
-    private FloatingContentCoordinator mFloatingContentCoordinator;
-
-    @Mock
-    private DeviceConfigProxy mDeviceConfigProxy;
-
-    private PipSnapAlgorithm mPipSnapAlgorithm;
-    private PipMotionHelper mMotionHelper;
-    private PipResizeGestureHandler mPipResizeGestureHandler;
-
-    Rect mInsetBounds;
-    Rect mMinBounds;
-    Rect mCurBounds;
-    boolean mFromImeAdjustment;
-    boolean mFromShelfAdjustment;
-    int mDisplayRotation;
-
-
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-        mPipTouchHandler = new PipTouchHandler(mContext, mActivityManager, mIActivityTaskManager,
-                mPipMenuActivityController, mInputConsumerController, mPipBoundsHandler,
-                mPipTaskOrganizer, mFloatingContentCoordinator, mDeviceConfigProxy);
-        mPipSnapAlgorithm = new PipSnapAlgorithm(mContext);
-        mMotionHelper = Mockito.spy(mPipTouchHandler.getMotionHelper());
-        mPipResizeGestureHandler = Mockito.spy(mPipTouchHandler.getPipResizeGestureHandler());
-        mPipTouchHandler.setPipMotionHelper(mMotionHelper);
-        mPipTouchHandler.setPipResizeGestureHandler(mPipResizeGestureHandler);
-
-        // Assume a display of 1000 x 1000
-        // inset of 10
-        mInsetBounds = new Rect(10, 10, 990, 990);
-        // minBounds of 100x100 bottom right corner
-        mMinBounds = new Rect(890, 890, 990, 990);
-        mCurBounds = new Rect();
-        mFromImeAdjustment = false;
-        mFromShelfAdjustment = false;
-        mDisplayRotation = 0;
-    }
-
-    @Test
-    public void updateMovementBounds_minBounds() {
-        Rect expectedMinMovementBounds = new Rect();
-        mPipSnapAlgorithm.getMovementBounds(mMinBounds, mInsetBounds, expectedMinMovementBounds, 0);
-
-        mPipTouchHandler.onMovementBoundsChanged(mInsetBounds, mMinBounds, mCurBounds,
-                mFromImeAdjustment, mFromShelfAdjustment, mDisplayRotation);
-
-        assertEquals(expectedMinMovementBounds, mPipTouchHandler.mMinMovementBounds);
-        verify(mPipResizeGestureHandler, times(1))
-                .updateMinSize(mMinBounds.width(), mMinBounds.height());
-    }
-
-    @Test
-    public void updateMovementBounds_maxBounds() {
-        Point displaySize = new Point();
-        mContext.getDisplay().getRealSize(displaySize);
-        Size maxSize = mPipSnapAlgorithm.getSizeForAspectRatio(1,
-                mContext.getResources().getDimensionPixelSize(
-                        R.dimen.pip_expanded_shortest_edge_size), displaySize.x, displaySize.y);
-        Rect maxBounds = new Rect(0, 0, maxSize.getWidth(), maxSize.getHeight());
-        Rect expectedMaxMovementBounds = new Rect();
-        mPipSnapAlgorithm.getMovementBounds(maxBounds, mInsetBounds, expectedMaxMovementBounds, 0);
-
-        mPipTouchHandler.onMovementBoundsChanged(mInsetBounds, mMinBounds, mCurBounds,
-                mFromImeAdjustment, mFromShelfAdjustment, mDisplayRotation);
-
-        assertEquals(expectedMaxMovementBounds, mPipTouchHandler.mMaxMovementBounds);
-        verify(mPipResizeGestureHandler, times(1))
-                .updateMaxSize(maxBounds.width(), maxBounds.height());
-    }
-
-    @Test
-    public void updateMovementBounds_withImeAdjustment_movesPip() {
-        mFromImeAdjustment = true;
-        mPipTouchHandler.onMovementBoundsChanged(mInsetBounds, mMinBounds, mCurBounds,
-                mFromImeAdjustment, mFromShelfAdjustment, mDisplayRotation);
-
-        verify(mMotionHelper, times(1)).animateToOffset(any(), anyInt());
-    }
-}
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 485127a..31044d0 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -986,4 +986,11 @@
      * Returns MIME types contained in {@code mimeGroup} from {@code packageName} package
      */
     public abstract List<String> getMimeGroup(String packageName, String mimeGroup);
+
+    /**
+     * Toggles visibility logging to help in debugging the app enumeration feature.
+     * @param packageName the package name that should begin logging
+     * @param enabled true if visibility blocks should be logged
+     */
+    public abstract void setVisibilityLogging(String packageName, boolean enabled);
 }
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index 0ad0b23..b90681d 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -43,6 +43,7 @@
 import android.util.ArraySet;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.SparseBooleanArray;
 import android.util.SparseSetArray;
 
 import com.android.internal.R;
@@ -123,6 +124,7 @@
     }
 
     public interface FeatureConfig {
+
         /** Called when the system is ready and components can be queried. */
         void onSystemReady();
 
@@ -132,11 +134,21 @@
         /** @return true if the feature is enabled for the given package. */
         boolean packageIsEnabled(AndroidPackage pkg);
 
+        /** @return true if debug logging is enabled for the given package. */
+        boolean isLoggingEnabled(int appId);
+
+        /**
+         * Turns on logging for the given appId
+         * @param enable true if logging should be enabled, false if disabled.
+         */
+        void enableLogging(int appId, boolean enable);
+
         /**
          * Initializes the package enablement state for the given package. This gives opportunity
          * to do any expensive operations ahead of the actual checks.
+         * @param removed true if adding, false if removing
          */
-        void initializePackageState(String packageName);
+        void updatePackageState(PackageSetting setting, boolean removed);
     }
 
     private static class FeatureConfigImpl implements FeatureConfig, CompatChange.ChangeListener {
@@ -147,6 +159,9 @@
                 PackageManager.APP_ENUMERATION_ENABLED_BY_DEFAULT;
         private final ArraySet<String> mDisabledPackages = new ArraySet<>();
 
+        @Nullable
+        private SparseBooleanArray mLoggingEnabled = null;
+
         private FeatureConfigImpl(
                 PackageManagerInternal pmInternal, PackageManagerService.Injector injector) {
             mPmInternal = pmInternal;
@@ -192,39 +207,65 @@
             }
         }
 
-        private boolean fetchPackageIsEnabled(AndroidPackage pkg) {
+        @Override
+        public boolean isLoggingEnabled(int uid) {
+            return mLoggingEnabled != null && mLoggingEnabled.indexOfKey(uid) >= 0;
+        }
+
+        @Override
+        public void enableLogging(int appId, boolean enable) {
+            if (enable) {
+                if (mLoggingEnabled == null) {
+                    mLoggingEnabled = new SparseBooleanArray();
+                }
+                mLoggingEnabled.put(appId, true);
+            } else {
+                if (mLoggingEnabled != null) {
+                    final int index = mLoggingEnabled.indexOfKey(appId);
+                    if (index >= 0) {
+                        mLoggingEnabled.removeAt(index);
+                        if (mLoggingEnabled.size() == 0) {
+                            mLoggingEnabled = null;
+                        }
+                    }
+                }
+            }
+        }
+
+        @Override
+        public void onCompatChange(String packageName) {
+            updateEnabledState(mPmInternal.getPackage(packageName));
+        }
+
+        private void updateEnabledState(AndroidPackage pkg) {
             final long token = Binder.clearCallingIdentity();
             try {
                 // TODO(b/135203078): Do not use toAppInfo
-                final boolean changeEnabled =
+                final boolean enabled =
                         mInjector.getCompatibility().isChangeEnabled(
                                 PackageManager.FILTER_APPLICATION_QUERY,
                                 pkg.toAppInfoWithoutState());
-                return changeEnabled;
+                if (enabled) {
+                    mDisabledPackages.remove(pkg.getPackageName());
+                } else {
+                    mDisabledPackages.add(pkg.getPackageName());
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
         }
 
         @Override
-        public void onCompatChange(String packageName) {
-            final AndroidPackage pkg = mPmInternal.getPackage(packageName);
-            if (pkg == null) {
-                mDisabledPackages.remove(packageName);
-                return;
-            }
-            boolean enabled = fetchPackageIsEnabled(pkg);
-            if (enabled) {
-                mDisabledPackages.remove(packageName);
+        public void updatePackageState(PackageSetting setting, boolean removed) {
+            final boolean enableLogging =
+                    !removed && (setting.pkg.isTestOnly() || setting.pkg.isDebuggable());
+            enableLogging(setting.appId, enableLogging);
+            if (removed) {
+                mDisabledPackages.remove(setting.pkg.getPackageName());
             } else {
-                mDisabledPackages.add(packageName);
+                updateEnabledState(setting.pkg);
             }
         }
-
-        @Override
-        public void initializePackageState(String packageName) {
-            onCompatChange(packageName);
-        }
     }
 
     /** Builder method for an AppsFilter */
@@ -250,6 +291,10 @@
                 forceSystemAppsQueryable, null);
     }
 
+    public FeatureConfig getFeatureConfig() {
+        return mFeatureConfig;
+    }
+
     /** Returns true if the querying package may query for the potential target package */
     private static boolean canQueryViaComponents(AndroidPackage querying,
             AndroidPackage potentialTarget) {
@@ -447,7 +492,7 @@
                 }
             }
             mOverlayReferenceMapper.addPkg(newPkgSetting.pkg, existingPkgs);
-            mFeatureConfig.initializePackageState(newPkgSetting.pkg.getPackageName());
+            mFeatureConfig.updatePackageState(newPkgSetting, false /*removed*/);
         } finally {
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         }
@@ -499,7 +544,7 @@
         }
 
         mOverlayReferenceMapper.removePkg(setting.name);
-        mFeatureConfig.initializePackageState(setting.pkg.getPackageName());
+        mFeatureConfig.updatePackageState(setting, true /*removed*/);
     }
 
     /**
@@ -516,13 +561,13 @@
             PackageSetting targetPkgSetting, int userId) {
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplication");
         try {
-            if (!shouldFilterApplicationInternal(callingUid, callingSetting, targetPkgSetting,
-                    userId)) {
+
+            if (!shouldFilterApplicationInternal(
+                    callingUid, callingSetting, targetPkgSetting, userId)) {
                 return false;
             }
-            if (DEBUG_LOGGING) {
-                log(callingSetting, targetPkgSetting,
-                        DEBUG_ALLOW_ALL ? "ALLOWED" : "BLOCKED", new RuntimeException());
+            if (DEBUG_LOGGING || mFeatureConfig.isLoggingEnabled(UserHandle.getAppId(callingUid))) {
+                log(callingSetting, targetPkgSetting, "BLOCKED");
             }
             return !DEBUG_ALLOW_ALL;
         } finally {
@@ -737,17 +782,11 @@
         }
     }
 
-    private static void log(SettingBase callingPkgSetting, PackageSetting targetPkgSetting,
+    private static void log(SettingBase callingSetting, PackageSetting targetPkgSetting,
             String description) {
-        log(callingPkgSetting, targetPkgSetting, description, null);
-    }
-
-    private static void log(SettingBase callingPkgSetting, PackageSetting targetPkgSetting,
-            String description, Throwable throwable) {
-        Slog.wtf(TAG,
-                "interaction: " + callingPkgSetting
-                        + " -> " + targetPkgSetting + " "
-                        + description, throwable);
+        Slog.i(TAG,
+                "interaction: " + (callingSetting == null ? "system" : callingSetting) + " -> "
+                        + targetPkgSetting + " " + description);
     }
 
     public void dumpQueries(
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index a8996d5..3a0daf1 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -6838,7 +6838,7 @@
                                 || (matchVisibleToInstantAppOnly && isCallerInstantApp
                                         && isTargetHiddenFromInstantApp));
                 final boolean blockNormalResolution = !isTargetInstantApp && !isCallerInstantApp
-                        && !resolveForStart && shouldFilterApplicationLocked(
+                        && shouldFilterApplicationLocked(
                                 getPackageSettingInternal(ai.applicationInfo.packageName,
                                         Process.SYSTEM_UID), filterCallingUid, userId);
                 if (!blockInstantResolution && !blockNormalResolution) {
@@ -24152,6 +24152,18 @@
         public List<String> getMimeGroup(String packageName, String mimeGroup) {
             return PackageManagerService.this.getMimeGroup(packageName, mimeGroup);
         }
+
+        @Override
+        public void setVisibilityLogging(String packageName, boolean enable) {
+            final PackageSetting pkg;
+            synchronized (mLock) {
+                pkg = mSettings.getPackageLPr(packageName);
+            }
+            if (pkg == null) {
+                throw new IllegalStateException("No package found for " + packageName);
+            }
+            mAppsFilter.getFeatureConfig().enableLogging(pkg.appId, enable);
+        }
     }
 
     @GuardedBy("mLock")
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 0f06c18..be17dd8 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -295,6 +295,8 @@
                     return runRollbackApp();
                 case "get-moduleinfo":
                     return runGetModuleInfo();
+                case "log-visibility":
+                    return runLogVisibility();
                 default: {
                     String nextArg = getNextArg();
                     if (nextArg == null) {
@@ -360,6 +362,36 @@
         return 1;
     }
 
+    private int runLogVisibility() {
+        final PrintWriter pw = getOutPrintWriter();
+        boolean enable = true;
+
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case "--disable":
+                    enable = false;
+                    break;
+                case "--enable":
+                    enable = true;
+                    break;
+                default:
+                    pw.println("Error: Unknown option: " + opt);
+                    return -1;
+            }
+        }
+
+        String packageName = getNextArg();
+        if (packageName != null) {
+            LocalServices.getService(PackageManagerInternal.class)
+                    .setVisibilityLogging(packageName, enable);
+        } else {
+            getErrPrintWriter().println("Error: no package specified");
+            return -1;
+        }
+        return 1;
+    }
+
     private int uninstallSystemUpdates() {
         final PrintWriter pw = getOutPrintWriter();
         List<String> failedUninstalls = new LinkedList<>();
@@ -3715,6 +3747,11 @@
         pw.println("      --all: show all module info");
         pw.println("      --installed: show only installed modules");
         pw.println("");
+        pw.println("  log-visibility [--enable|--disable] <PACKAGE>");
+        pw.println("    Turns on debug logging when visibility is blocked for the given package.");
+        pw.println("      --enable: turn on debug logging (default)");
+        pw.println("      --disable: turn off debug logging");
+        pw.println("");
         Intent.printIntentArgsHelp(pw , "");
     }
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index eed3d9d..2a34bbe 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -3297,22 +3297,24 @@
     }
 
 
-    public DeviceAdminInfo findAdmin(ComponentName adminName, int userHandle,
+    public DeviceAdminInfo findAdmin(final ComponentName adminName, final int userHandle,
             boolean throwForMissingPermission) {
         if (!mHasFeature) {
             return null;
         }
         enforceFullCrossUsersPermission(userHandle);
-        ActivityInfo ai = null;
-        try {
-            ai = mIPackageManager.getReceiverInfo(adminName,
-                    PackageManager.GET_META_DATA |
-                    PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS |
-                    PackageManager.MATCH_DIRECT_BOOT_AWARE |
-                    PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
-        } catch (RemoteException e) {
-            // shouldn't happen.
-        }
+        final ActivityInfo ai = mInjector.binderWithCleanCallingIdentity(() -> {
+            try {
+                return mIPackageManager.getReceiverInfo(adminName,
+                        PackageManager.GET_META_DATA
+                        | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
+                        | PackageManager.MATCH_DIRECT_BOOT_AWARE
+                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
+            } catch (RemoteException e) {
+                // shouldn't happen.
+                return null;
+            }
+        });
         if (ai == null) {
             throw new IllegalArgumentException("Unknown admin: " + adminName);
         }
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index 37d3d32..bc5cc96 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -20,6 +20,7 @@
 
 import android.Manifest;
 import android.annotation.IntDef;
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -719,9 +720,9 @@
      *                      23.040 9.2.3.24.16
      * @param languageShiftTable GSM national language shift table to use, specified by 3GPP
      *                           23.040 9.2.3.24.15
-     * @param refNumber parameter to create SmsHeader
-     * @param seqNumber parameter to create SmsHeader
-     * @param msgCount parameter to create SmsHeader
+     * @param refNumber reference number of concatenated SMS, specified by 3GPP 23.040 9.2.3.24.1
+     * @param seqNumber sequence number of concatenated SMS, specified by 3GPP 23.040 9.2.3.24.1
+     * @param msgCount count of messages of concatenated SMS, specified by 3GPP 23.040 9.2.3.24.2
      * @return a byte[] containing the encoded message
      *
      * @hide
@@ -730,11 +731,14 @@
     @SystemApi
     @NonNull
     public static byte[] getSubmitPduEncodedMessage(boolean isTypeGsm,
-            @NonNull String destinationAddress,
-            @NonNull String message,
-            @EncodingSize int encoding, int languageTable,
-            int languageShiftTable, int refNumber,
-            int seqNumber, int msgCount) {
+                                                    @NonNull String destinationAddress,
+                                                    @NonNull String message,
+                                                    @EncodingSize int encoding,
+                                                    @IntRange(from = 0) int languageTable,
+                                                    @IntRange(from = 0) int languageShiftTable,
+                                                    @IntRange(from = 0, to = 255) int refNumber,
+                                                    @IntRange(from = 1, to = 255) int seqNumber,
+                                                    @IntRange(from = 1, to = 255) int msgCount) {
         byte[] data;
         SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
         concatRef.refNumber = refNumber;