Merge "Make sure to send HOVER_EXIT when starting touch exploration if we haven't sent it already." into main
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 9b16949..c8dbfc9 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -53,6 +53,7 @@
 import android.graphics.drawable.DrawableInflater;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.SystemClock;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.AttributeSet;
@@ -132,6 +133,11 @@
     private static final Object sSync = new Object();
     private final Object mUpdateLock = new Object();
 
+    /**
+     * Controls whether we should preload resources during zygote init.
+     */
+    private static final boolean PRELOAD_RESOURCES = true;
+
     // Used by BridgeResources in layoutlib
     @UnsupportedAppUsage
     static Resources mSystem = null;
@@ -2666,6 +2672,98 @@
         }
     }
 
+    /**
+     * Load in commonly used resources, so they can be shared across processes.
+     *
+     * These tend to be a few Kbytes, but are frequently in the 20-40K range, and occasionally even
+     * larger.
+     * @hide
+     */
+    @UnsupportedAppUsage
+    public static void preloadResources() {
+        try {
+            final Resources sysRes = Resources.getSystem();
+            sysRes.startPreloading();
+            if (PRELOAD_RESOURCES) {
+                Log.i(TAG, "Preloading resources...");
+
+                long startTime = SystemClock.uptimeMillis();
+                TypedArray ar = sysRes.obtainTypedArray(
+                        com.android.internal.R.array.preloaded_drawables);
+                int numberOfEntries = preloadDrawables(sysRes, ar);
+                ar.recycle();
+                Log.i(TAG, "...preloaded " + numberOfEntries + " resources in "
+                        + (SystemClock.uptimeMillis() - startTime) + "ms.");
+
+                startTime = SystemClock.uptimeMillis();
+                ar = sysRes.obtainTypedArray(
+                        com.android.internal.R.array.preloaded_color_state_lists);
+                numberOfEntries = preloadColorStateLists(sysRes, ar);
+                ar.recycle();
+                Log.i(TAG, "...preloaded " + numberOfEntries + " resources in "
+                        + (SystemClock.uptimeMillis() - startTime) + "ms.");
+
+                if (sysRes.getBoolean(
+                        com.android.internal.R.bool.config_freeformWindowManagement)) {
+                    startTime = SystemClock.uptimeMillis();
+                    ar = sysRes.obtainTypedArray(
+                            com.android.internal.R.array.preloaded_freeform_multi_window_drawables);
+                    numberOfEntries = preloadDrawables(sysRes, ar);
+                    ar.recycle();
+                    Log.i(TAG, "...preloaded " + numberOfEntries + " resource in "
+                            + (SystemClock.uptimeMillis() - startTime) + "ms.");
+                }
+            }
+            sysRes.finishPreloading();
+        } catch (RuntimeException e) {
+            Log.w(TAG, "Failure preloading resources", e);
+        }
+    }
+
+    private static int preloadColorStateLists(Resources resources, TypedArray ar) {
+        final int numberOfEntries = ar.length();
+        for (int i = 0; i < numberOfEntries; i++) {
+            int id = ar.getResourceId(i, 0);
+
+            if (id != 0) {
+                if (resources.getColorStateList(id, null) == null) {
+                    throw new IllegalArgumentException(
+                            "Unable to find preloaded color resource #0x"
+                                    + Integer.toHexString(id)
+                                    + " (" + ar.getString(i) + ")");
+                }
+            }
+        }
+        return numberOfEntries;
+    }
+
+    private static int preloadDrawables(Resources resources, TypedArray ar) {
+        final int numberOfEntries = ar.length();
+        for (int i = 0; i < numberOfEntries; i++) {
+            int id = ar.getResourceId(i, 0);
+
+            if (id != 0) {
+                if (resources.getDrawable(id, null) == null) {
+                    throw new IllegalArgumentException(
+                            "Unable to find preloaded drawable resource #0x"
+                                    + Integer.toHexString(id)
+                                    + " (" + ar.getString(i) + ")");
+                }
+            }
+        }
+        return numberOfEntries;
+    }
+
+    /**
+     * Clear the cache when the framework resources packages is changed.
+     * @hide
+     */
+    @VisibleForTesting
+    public static void resetPreloadDrawableStateCache() {
+        ResourcesImpl.resetDrawableStateCache();
+        preloadResources();
+    }
+
     /** @hide */
     public void dump(PrintWriter pw, String prefix) {
         pw.println(prefix + "class=" + getClass());
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 3bb237a..480e43e 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -52,6 +52,7 @@
 import android.util.Xml;
 import android.view.DisplayAdjustments;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.GrowingArrayUtils;
 
 import libcore.util.NativeAllocationRegistry;
@@ -159,6 +160,23 @@
     }
 
     /**
+     * Clear the cache when the framework resources packages is changed.
+     *
+     * It's only used in the test initial function instead of regular app behaviors. It doesn't
+     * guarantee the thread-safety so mark this with @VisibleForTesting.
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    static void resetDrawableStateCache() {
+        synchronized (sSync) {
+            sPreloadedDrawables[0].clear();
+            sPreloadedDrawables[1].clear();
+            sPreloadedColorDrawables.clear();
+            sPreloadedComplexColors.clear();
+            sPreloaded = false;
+        }
+    }
+
+    /**
      * Creates a new ResourcesImpl object with CompatibilityInfo.
      *
      * @param assets Previously created AssetManager.
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 5d0a723..3f04ca4 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -943,16 +943,19 @@
      * @hide
      */
     @VisibleForTesting
-    public final @NonNull String getTransactionTraceName(int transactionCode) {
+    public final @Nullable String getTransactionTraceName(int transactionCode) {
+        final boolean isInterfaceUserDefined = getMaxTransactionId() == 0;
         if (mTransactionTraceNames == null) {
-            final int highestId = Math.min(getMaxTransactionId(), TRANSACTION_TRACE_NAME_ID_LIMIT);
+            final int highestId = isInterfaceUserDefined ? TRANSACTION_TRACE_NAME_ID_LIMIT
+                    : Math.min(getMaxTransactionId(), TRANSACTION_TRACE_NAME_ID_LIMIT);
             mSimpleDescriptor = getSimpleDescriptor();
             mTransactionTraceNames = new AtomicReferenceArray(highestId + 1);
         }
 
-        final int index = transactionCode - FIRST_CALL_TRANSACTION;
-        if (index < 0 || index >= mTransactionTraceNames.length()) {
-            return mSimpleDescriptor + "#" + transactionCode;
+        final int index = isInterfaceUserDefined
+                ? transactionCode : transactionCode - FIRST_CALL_TRANSACTION;
+        if (index >= mTransactionTraceNames.length() || index < 0) {
+            return null;
         }
 
         String transactionTraceName = mTransactionTraceNames.getAcquire(index);
@@ -1317,19 +1320,9 @@
         final boolean hasFullyQualifiedName = getMaxTransactionId() > 0;
         final String transactionTraceName;
 
-        if (tagEnabled && hasFullyQualifiedName) {
+        if (tagEnabled) {
             // If tracing enabled and we have a fully qualified name, fetch the name
             transactionTraceName = getTransactionTraceName(code);
-        } else if (tagEnabled && isStackTrackingEnabled()) {
-            // If tracing is enabled and we *don't* have a fully qualified name, fetch the
-            // 'best effort' name only for stack tracking. This works around noticeable perf impact
-            // on low latency binder calls (<100us). The tracing call itself is between (1-10us) and
-            // the perf impact can be quite noticeable while benchmarking such binder calls.
-            // The primary culprits are ContentProviders and Cursors which convenienty don't
-            // autogenerate their AIDL and hence will not have a fully qualified name.
-            //
-            // TODO(b/253426478): Relax this constraint after a more robust fix
-            transactionTraceName = getTransactionTraceName(code);
         } else {
             transactionTraceName = null;
         }
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 85cb15b..b3938b4 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -26,7 +26,6 @@
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.pm.SharedLibraryInfo;
 import android.content.res.Resources;
-import android.content.res.TypedArray;
 import android.os.Build;
 import android.os.Environment;
 import android.os.IInstalld;
@@ -102,21 +101,10 @@
     private static final String SOCKET_NAME_ARG = "--socket-name=";
 
     /**
-     * Used to pre-load resources.
-     */
-    @UnsupportedAppUsage
-    private static Resources mResources;
-
-    /**
      * The path of a file that contains classes to preload.
      */
     private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes";
 
-    /**
-     * Controls whether we should preload resources during zygote init.
-     */
-    private static final boolean PRELOAD_RESOURCES = true;
-
     private static final int UNPRIVILEGED_UID = 9999;
     private static final int UNPRIVILEGED_GID = 9999;
 
@@ -143,7 +131,7 @@
         cacheNonBootClasspathClassLoaders();
         bootTimingsTraceLog.traceEnd(); // CacheNonBootClasspathClassLoaders
         bootTimingsTraceLog.traceBegin("PreloadResources");
-        preloadResources();
+        Resources.preloadResources();
         bootTimingsTraceLog.traceEnd(); // PreloadResources
         Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadAppProcessHALs");
         nativePreloadAppProcessHALs();
@@ -414,87 +402,6 @@
     }
 
     /**
-     * Load in commonly used resources, so they can be shared across processes.
-     *
-     * These tend to be a few Kbytes, but are frequently in the 20-40K range, and occasionally even
-     * larger.
-     */
-    private static void preloadResources() {
-        try {
-            mResources = Resources.getSystem();
-            mResources.startPreloading();
-            if (PRELOAD_RESOURCES) {
-                Log.i(TAG, "Preloading resources...");
-
-                long startTime = SystemClock.uptimeMillis();
-                TypedArray ar = mResources.obtainTypedArray(
-                        com.android.internal.R.array.preloaded_drawables);
-                int N = preloadDrawables(ar);
-                ar.recycle();
-                Log.i(TAG, "...preloaded " + N + " resources in "
-                        + (SystemClock.uptimeMillis() - startTime) + "ms.");
-
-                startTime = SystemClock.uptimeMillis();
-                ar = mResources.obtainTypedArray(
-                        com.android.internal.R.array.preloaded_color_state_lists);
-                N = preloadColorStateLists(ar);
-                ar.recycle();
-                Log.i(TAG, "...preloaded " + N + " resources in "
-                        + (SystemClock.uptimeMillis() - startTime) + "ms.");
-
-                if (mResources.getBoolean(
-                        com.android.internal.R.bool.config_freeformWindowManagement)) {
-                    startTime = SystemClock.uptimeMillis();
-                    ar = mResources.obtainTypedArray(
-                            com.android.internal.R.array.preloaded_freeform_multi_window_drawables);
-                    N = preloadDrawables(ar);
-                    ar.recycle();
-                    Log.i(TAG, "...preloaded " + N + " resource in "
-                            + (SystemClock.uptimeMillis() - startTime) + "ms.");
-                }
-            }
-            mResources.finishPreloading();
-        } catch (RuntimeException e) {
-            Log.w(TAG, "Failure preloading resources", e);
-        }
-    }
-
-    private static int preloadColorStateLists(TypedArray ar) {
-        int N = ar.length();
-        for (int i = 0; i < N; i++) {
-            int id = ar.getResourceId(i, 0);
-
-            if (id != 0) {
-                if (mResources.getColorStateList(id, null) == null) {
-                    throw new IllegalArgumentException(
-                            "Unable to find preloaded color resource #0x"
-                                    + Integer.toHexString(id)
-                                    + " (" + ar.getString(i) + ")");
-                }
-            }
-        }
-        return N;
-    }
-
-
-    private static int preloadDrawables(TypedArray ar) {
-        int N = ar.length();
-        for (int i = 0; i < N; i++) {
-            int id = ar.getResourceId(i, 0);
-
-            if (id != 0) {
-                if (mResources.getDrawable(id, null) == null) {
-                    throw new IllegalArgumentException(
-                            "Unable to find preloaded drawable resource #0x"
-                                    + Integer.toHexString(id)
-                                    + " (" + ar.getString(i) + ")");
-                }
-            }
-        }
-        return N;
-    }
-
-    /**
      * Runs several special GCs to try to clean up a few generations of softly- and final-reachable
      * objects, along with any other garbage. This is only useful just before a fork().
      */
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index c198797..9dce5e3 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -40,7 +40,6 @@
 #include <binder/Stability.h>
 #include <binderthreadstate/CallerUtils.h>
 #include <cutils/atomic.h>
-#include <cutils/threads.h>
 #include <log/log.h>
 #include <utils/KeyedVector.h>
 #include <utils/List.h>
diff --git a/core/tests/coretests/src/android/os/AidlTest.java b/core/tests/coretests/src/android/os/AidlTest.java
index 5f54b09..d0c3470 100644
--- a/core/tests/coretests/src/android/os/AidlTest.java
+++ b/core/tests/coretests/src/android/os/AidlTest.java
@@ -28,12 +28,14 @@
 
     private IAidlTest mRemote;
     private AidlObject mLocal;
+    private NonAutoGeneratedObject mNonAutoGenerated;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
         mLocal = new AidlObject();
         mRemote = IAidlTest.Stub.asInterface(mLocal);
+        mNonAutoGenerated = new NonAutoGeneratedObject("NonAutoGeneratedObject");
     }
 
     private static boolean check(TestParcelable p, int n, String s) {
@@ -84,6 +86,12 @@
         }
     }
 
+    private static class NonAutoGeneratedObject extends Binder {
+        NonAutoGeneratedObject(String descriptor) {
+            super(descriptor);
+        }
+    }
+
     private static class AidlObject extends IAidlTest.Stub {
         public IInterface queryLocalInterface(String descriptor) {
             // overriding this to return null makes asInterface always
@@ -194,7 +202,7 @@
                 TestParcelable[] a1, TestParcelable[] a2) {
             return null;
         }
-        
+
         public void voidSecurityException() {
             throw new SecurityException("gotcha!");
         }
@@ -396,7 +404,7 @@
         assertEquals("s2[1]", s2[1]);
         assertEquals("s2[2]", s2[2]);
     }
-    
+
     @SmallTest
     public void testVoidSecurityException() throws Exception {
         boolean good = false;
@@ -407,7 +415,7 @@
         }
         assertEquals(good, true);
     }
-    
+
     @SmallTest
     public void testIntSecurityException() throws Exception {
         boolean good = false;
@@ -420,7 +428,7 @@
     }
 
     @SmallTest
-    public void testGetTransactionName() throws Exception {
+    public void testGetTransactionNameAutoGenerated() throws Exception {
         assertEquals(15, mLocal.getMaxTransactionId());
 
         assertEquals("booleanArray",
@@ -430,12 +438,21 @@
         assertEquals("parcelableIn",
                 mLocal.getTransactionName(IAidlTest.Stub.TRANSACTION_parcelableIn));
 
-        assertEquals("IAidlTest:booleanArray",
+        assertEquals("AIDL::java::IAidlTest::booleanArray::server",
                 mLocal.getTransactionTraceName(IAidlTest.Stub.TRANSACTION_booleanArray));
-        assertEquals("IAidlTest:voidSecurityException",
+        assertEquals("AIDL::java::IAidlTest::voidSecurityException::server",
                 mLocal.getTransactionTraceName(IAidlTest.Stub.TRANSACTION_voidSecurityException));
-        assertEquals("IAidlTest:parcelableIn",
+        assertEquals("AIDL::java::IAidlTest::parcelableIn::server",
                 mLocal.getTransactionTraceName(IAidlTest.Stub.TRANSACTION_parcelableIn));
     }
-}
 
+    @SmallTest
+    public void testGetTransactionNameNonAutoGenerated() throws Exception {
+        assertEquals(0, mNonAutoGenerated.getMaxTransactionId());
+
+        assertEquals("AIDL::java::NonAutoGeneratedObject::#0::server",
+                mNonAutoGenerated.getTransactionTraceName(0));
+        assertEquals("AIDL::java::NonAutoGeneratedObject::#1::server",
+                mNonAutoGenerated.getTransactionTraceName(1));
+    }
+}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index b83ab38..4c234a0 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -3449,8 +3449,14 @@
                         hdmiClient = mHdmiTvClient;
                     }
 
-                    if (((mHdmiPlaybackClient != null && isFullVolumeDevice(device))
-                            || (mHdmiTvClient != null && mHdmiSystemAudioSupported))
+                    boolean playbackDeviceConditions = mHdmiPlaybackClient != null
+                            && isFullVolumeDevice(device);
+                    boolean tvConditions = mHdmiTvClient != null
+                            && mHdmiSystemAudioSupported
+                            && !isAbsoluteVolumeDevice(device)
+                            && !isA2dpAbsoluteVolumeDevice(device);
+
+                    if ((playbackDeviceConditions || tvConditions)
                             && mHdmiCecVolumeControlEnabled
                             && streamTypeAlias == AudioSystem.STREAM_MUSIC) {
                         int keyCode = KeyEvent.KEYCODE_UNKNOWN;
diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java
index c0e191f..5a941fe 100644
--- a/services/core/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java
@@ -80,6 +80,8 @@
     // Append targetSdkVersion=n to existing seinfo label where n is the app's targetSdkVersion
     private static final String TARGETSDKVERSION_STR = ":targetSdkVersion=";
 
+    private static final String PARTITION_STR = ":partition=";
+
     /**
      * Allows opt-in to the latest targetSdkVersion enforced changes without changing target SDK.
      * Turning this change on for an app targeting the latest SDK or higher is a no-op.
@@ -370,6 +372,23 @@
         return pkg.getTargetSdkVersion();
     }
 
+    private static String getPartition(AndroidPackage pkg) {
+        if (pkg.isSystemExt()) {
+            return "system_ext";
+        } else if (pkg.isProduct()) {
+            return "product";
+        } else if (pkg.isVendor()) {
+            return "vendor";
+        } else if (pkg.isOem()) {
+            return "oem";
+        } else if (pkg.isOdm()) {
+            return "odm";
+        } else if (pkg.isSystem()) {
+            return "system";
+        }
+        return "";
+    }
+
     /**
      * Selects a security label to a package based on input parameters and the seinfo tag taken
      * from a matched policy. All signature based policy stanzas are consulted and, if no match
@@ -433,6 +452,11 @@
 
         seInfo += TARGETSDKVERSION_STR + targetSdkVersion;
 
+        String partition = getPartition(pkg);
+        if (!partition.isEmpty()) {
+            seInfo += PARTITION_STR + partition;
+        }
+
         if (DEBUG_POLICY_INSTALL) {
             Slog.i(TAG, "package (" + pkg.getPackageName() + ") labeled with "
                     + "seinfo=" + seInfo);
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index 9ed5aa7..5221cfa 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -2116,6 +2116,12 @@
                 if (!isStorageOrMedia) {
                     continue;
                 }
+                boolean isSystemOrPolicyFixed = (getPermissionFlags(newPackage.getPackageName(),
+                        permInfo.name, userId) & (FLAG_PERMISSION_SYSTEM_FIXED
+                        | FLAG_PERMISSION_POLICY_FIXED)) != 0;
+                if (isSystemOrPolicyFixed) {
+                    continue;
+                }
 
                 EventLog.writeEvent(0x534e4554, "171430330", newPackage.getUid(),
                         "Revoking permission " + permInfo.name + " from package "
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index d947168..15bc60c 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -1089,21 +1089,13 @@
             }
 
             final int otherWindowingMode = other.getWindowingMode();
-            if (otherWindowingMode == WINDOWING_MODE_FULLSCREEN) {
-                if (isTranslucent(other, starting)) {
-                    // Can be visible behind a translucent fullscreen TaskFragment.
-                    gotTranslucentFullscreen = true;
-                    continue;
-                }
-                return TASK_FRAGMENT_VISIBILITY_INVISIBLE;
-            } else if (otherWindowingMode == WINDOWING_MODE_MULTI_WINDOW
-                    && other.matchParentBounds()) {
+            if (otherWindowingMode == WINDOWING_MODE_FULLSCREEN
+                    || (otherWindowingMode != WINDOWING_MODE_PINNED && other.matchParentBounds())) {
                 if (isTranslucent(other, starting)) {
                     // Can be visible behind a translucent TaskFragment.
                     gotTranslucentFullscreen = true;
                     continue;
                 }
-                // Multi-window TaskFragment that matches parent bounds would occlude other children
                 return TASK_FRAGMENT_VISIBILITY_INVISIBLE;
             }
 
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 45c092e..59a5b7e 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -174,7 +174,7 @@
     /**
      * Key to the backup & restore data byte array in the Bundle that is returned by {@link
      * #getAllSimSpecificSettingsForBackup()} or to be pass in to {@link
-     * #restoreAllSimSpecificSettings()}.
+     * #restoreAllSimSpecificSettingsFromBackup(byte[])}.
      *
      * @hide
      */
@@ -2218,46 +2218,46 @@
     }
 
     /**
-     * Get an array of subscription ids for specified logical SIM slot Index.
+     * Get an array of subscription ids for the specified logical SIM slot Index. The maximum size
+     * of the array is 1. This API was mistakenly designed to return multiple subscription ids,
+     * which is not possible in the current Android telephony architecture.
      *
      * @param slotIndex The logical SIM slot index.
      *
-     * @return subscription Ids or {@code null} if the given slot index is not valid or there are
-     * no active subscription in the slot. In the implementation today, there will be no more
-     * than one subscriptions per logical SIM slot.
+     * @return Subscription id of the active subscription on the specified logical SIM slot index.
+     * If SIM is absent on the slot, a single element array of {@link #INVALID_SUBSCRIPTION_ID} will
+     * be returned. {@code null} if the provided {@code slotIndex} is not valid.
      *
      * @deprecated Use {@link #getSubscriptionId(int)} instead.
      */
     @Deprecated
     @Nullable
     public int[] getSubscriptionIds(int slotIndex) {
-        int subId = getSubscriptionId(slotIndex);
-        if (!isValidSubscriptionId(subId)) {
+        if (!isValidSlotIndex(slotIndex)) {
             return null;
         }
         return new int[]{getSubscriptionId(slotIndex)};
     }
 
-    /** @hide */
-    @UnsupportedAppUsage
+    /**
+     * Get an array of subscription ids for the specified logical SIM slot Index. The maximum size
+     * of the array is 1. This API was mistakenly designed to return multiple subscription ids,
+     * which is not possible in the current Android telephony architecture.
+     *
+     * @param slotIndex The logical SIM slot index.
+     *
+     * @return Subscription id of the active subscription on the specified logical SIM slot index.
+     * If SIM is absent on the slot, a single element array of {@link #INVALID_SUBSCRIPTION_ID} will
+     * be returned. {@code null} if the provided {@code slotIndex} is not valid.
+     *
+     * @deprecated Use {@link #getSubscriptionId(int)} instead.
+     * @hide
+     */
     public static int[] getSubId(int slotIndex) {
         if (!isValidSlotIndex(slotIndex)) {
-            logd("[getSubId]- fail");
             return null;
         }
-
-        int[] subId = null;
-
-        try {
-            ISub iSub = TelephonyManager.getSubscriptionService();
-            if (iSub != null) {
-                subId = iSub.getSubIds(slotIndex);
-            }
-        } catch (RemoteException ex) {
-            // ignore it
-        }
-
-        return subId;
+        return new int[]{getSubscriptionId(slotIndex)};
     }
 
     /**
@@ -4027,39 +4027,16 @@
     }
 
     /**
-     * Called to attempt to restore the backed up sim-specific configs to device for specific sim.
-     * This will try to restore the data that was stored internally when {@link
-     * #restoreAllSimSpecificSettingsFromBackup(byte[] data)} was called during setup wizard.
-     * End result is SimInfoDB is modified to match any backed up configs for the requested
-     * inserted sim.
-     *
-     * <p>
-     * The {@link Uri} {@link #SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI} is notified if any SimInfoDB
-     * entry is updated as the result of this method call.
-     *
-     * @param iccId of the sim that a restore is requested for.
-     *
-     * @hide
-     */
-    @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
-    public void restoreSimSpecificSettingsForIccIdFromBackup(@NonNull String iccId) {
-        mContext.getContentResolver().call(
-                SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI,
-                RESTORE_SIM_SPECIFIC_SETTINGS_METHOD_NAME,
-                iccId, null);
-    }
-
-    /**
      * Called during setup wizard restore flow to attempt to restore the backed up sim-specific
-     * configs to device for all existing SIMs in SimInfoDB. Internally, it will store the backup
-     * data in an internal file. This file will persist on device for device's lifetime and will be
-     * used later on when a SIM is inserted to restore that specific SIM's settings by calling
-     * {@link #restoreSimSpecificSettingsForIccIdFromBackup(String iccId)}. End result is
-     * SimInfoDB is modified to match any backed up configs for the appropriate inserted SIMs.
+     * configs to device for all existing SIMs in the subscription database {@link SimInfo}.
+     * Internally, it will store the backup data in an internal file. This file will persist on
+     * device for device's lifetime and will be used later on when a SIM is inserted to restore that
+     * specific SIM's settings. End result is subscription database is modified to match any backed
+     * up configs for the appropriate inserted SIMs.
      *
      * <p>
-     * The {@link Uri} {@link #SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI} is notified if any SimInfoDB
-     * entry is updated as the result of this method call.
+     * The {@link Uri} {@link #SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI} is notified if any
+     * {@link SimInfo} entry is updated as the result of this method call.
      *
      * @param data with the sim specific configs to be backed up.
      *
@@ -4068,12 +4045,18 @@
     @SystemApi
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
     public void restoreAllSimSpecificSettingsFromBackup(@NonNull byte[] data) {
-        Bundle bundle = new Bundle();
-        bundle.putByteArray(KEY_SIM_SPECIFIC_SETTINGS_DATA, data);
-        mContext.getContentResolver().call(
-                SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI,
-                RESTORE_SIM_SPECIFIC_SETTINGS_METHOD_NAME,
-                null, bundle);
+        try {
+            ISub iSub = TelephonyManager.getSubscriptionService();
+            if (iSub != null) {
+                iSub.restoreAllSimSpecificSettingsFromBackup(data);
+            } else {
+                throw new IllegalStateException("subscription service unavailable.");
+            }
+        } catch (RemoteException ex) {
+            if (!isSystemProcess()) {
+                ex.rethrowAsRuntimeException();
+            }
+        }
     }
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index defa046..632a687 100644
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -236,8 +236,6 @@
 
     int getSlotIndex(int subId);
 
-    int[] getSubIds(int slotIndex);
-
     int getSubId(int slotIndex);
 
     int getDefaultSubId();
@@ -363,4 +361,20 @@
         */
        //TODO: Removed before U AOSP public release.
        boolean isSubscriptionManagerServiceEnabled();
+
+      /**
+       * Called during setup wizard restore flow to attempt to restore the backed up sim-specific
+       * configs to device for all existing SIMs in the subscription database
+       * {@link Telephony.SimInfo}. Internally, it will store the backup data in an internal file.
+       * This file will persist on device for device's lifetime and will be used later on when a SIM
+       * is inserted to restore that specific SIM's settings. End result is subscription database is
+       * modified to match any backed up configs for the appropriate inserted SIMs.
+       *
+       * <p>
+       * The {@link Uri} {@link #SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI} is notified if any
+       * {@link Telephony.SimInfo} entry is updated as the result of this method call.
+       *
+       * @param data with the sim specific configs to be backed up.
+       */
+       void restoreAllSimSpecificSettingsFromBackup(in byte[] data);
 }