Merge "settingslib/media: Add LeAudio support"
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index b574d04..172818d 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -311,6 +311,10 @@
 
 package android.provider {
 
+  public static final class ContactsContract.RawContactsEntity implements android.provider.BaseColumns android.provider.ContactsContract.DataColumns android.provider.ContactsContract.RawContactsColumns {
+    method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public static java.util.Map<java.lang.String,java.util.List<android.content.ContentValues>> queryRawContactEntity(@NonNull android.content.Context, long);
+  }
+
   public final class DeviceConfig {
     field public static final String NAMESPACE_ALARM_MANAGER = "alarm_manager";
     field public static final String NAMESPACE_APP_STANDBY = "app_standby";
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index c71fcc6..9caeb29 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -1186,11 +1186,6 @@
         mAttributionSource = attributionSource;
     }
 
-    /** {@hide} */
-    public void prepareToEnterProcess(@NonNull AttributionSource attributionSource) {
-        setAttributionSource(attributionSource);
-    }
-
     @Override
     public boolean equals(@Nullable Object o) {
         if (o instanceof BluetoothDevice) {
diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java
index 20152f3..b5df4db 100644
--- a/core/java/android/bluetooth/BluetoothManager.java
+++ b/core/java/android/bluetooth/BluetoothManager.java
@@ -62,15 +62,15 @@
     private static final String TAG = "BluetoothManager";
     private static final boolean DBG = false;
 
-    private final AttributionSource mAttributionSource;
+    private static AttributionSource sAttributionSource = null;
     private final BluetoothAdapter mAdapter;
 
     /**
      * @hide
      */
     public BluetoothManager(Context context) {
-        mAttributionSource = resolveAttributionSource(context);
-        mAdapter = BluetoothAdapter.createAdapter(mAttributionSource);
+        sAttributionSource = resolveAttributionSource(context);
+        mAdapter = BluetoothAdapter.createAdapter(sAttributionSource);
     }
 
     /** {@hide} */
@@ -79,6 +79,9 @@
         if (context != null) {
             res = context.getAttributionSource();
         }
+        else if (sAttributionSource != null) {
+            return sAttributionSource;
+        }
         if (res == null) {
             res = ActivityThread.currentAttributionSource();
         }
@@ -198,8 +201,8 @@
             IBluetoothGatt iGatt = managerService.getBluetoothGatt();
             if (iGatt == null) return devices;
             devices = Attributable.setAttributionSource(
-                    iGatt.getDevicesMatchingConnectionStates(states, mAttributionSource),
-                    mAttributionSource);
+                    iGatt.getDevicesMatchingConnectionStates(states, sAttributionSource),
+                    sAttributionSource);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index d811040..2fd437d 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -31,7 +31,6 @@
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.app.AppGlobals;
-import android.bluetooth.BluetoothDevice;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
@@ -11462,16 +11461,6 @@
         if (fromProtectedComponent) {
             mLocalFlags |= LOCAL_FLAG_FROM_PROTECTED_COMPONENT;
         }
-
-        // Special attribution fix-up logic for any BluetoothDevice extras
-        // passed via Bluetooth intents
-        if (mAction != null && mAction.startsWith("android.bluetooth.")
-                && hasExtra(BluetoothDevice.EXTRA_DEVICE)) {
-            final BluetoothDevice device = getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-            if (device != null) {
-                device.prepareToEnterProcess(source);
-            }
-        }
     }
 
     /** @hide */
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 0f0f123..a0f8615 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -37,6 +37,7 @@
 import android.content.ContextWrapper;
 import android.content.CursorEntityIterator;
 import android.content.Entity;
+import android.content.Entity.NamedContentValues;
 import android.content.EntityIterator;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -55,6 +56,7 @@
 import android.telecom.PhoneAccountHandle;
 import android.text.TextUtils;
 import android.util.DisplayMetrics;
+import android.util.Log;
 import android.util.Pair;
 import android.view.View;
 
@@ -64,7 +66,9 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 
@@ -5135,6 +5139,8 @@
      */
     public final static class RawContactsEntity
             implements BaseColumns, DataColumns, RawContactsColumns {
+        private static final String TAG = "ContactsContract.RawContactsEntity";
+
         /**
          * This utility class cannot be instantiated
          */
@@ -5187,6 +5193,73 @@
          * <P>Type: INTEGER</P>
          */
         public static final String DATA_ID = "data_id";
+
+        /**
+         * Query raw contacts entity by a contact ID, which can potentially be a corp profile
+         * contact ID
+         *
+         * @param context A context to get the ContentResolver from
+         * @param contactId Contact ID, which can potentialy be a corp profile contact ID.
+         *
+         * @return A map from a mimetype to a List of the entity content values.
+         * {@hide}
+         */
+        @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+        @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
+        public static @NonNull Map<String, List<ContentValues>> queryRawContactEntity(
+                @NonNull Context context, long contactId) {
+            Uri uri = RawContactsEntity.CONTENT_URI;
+            long realContactId = contactId;
+
+            if (Contacts.isEnterpriseContactId(contactId)) {
+                uri = RawContactsEntity.CORP_CONTENT_URI;
+                realContactId = contactId - Contacts.ENTERPRISE_CONTACT_ID_BASE;
+            }
+            final Map<String, List<ContentValues>> contentValuesListMap =
+                    new HashMap<String, List<ContentValues>>();
+            // The resolver may return the entity iterator with no data. It is possible.
+            // e.g. If all the data in the contact of the given contact id are not exportable ones,
+            //      they are hidden from the view of this method, though contact id itself exists.
+            EntityIterator entityIterator = null;
+            try {
+                final String selection = Data.CONTACT_ID + "=?";
+                final String[] selectionArgs = new String[] {String.valueOf(realContactId)};
+
+                entityIterator = RawContacts.newEntityIterator(context.getContentResolver().query(
+                            uri, null, selection, selectionArgs, null));
+
+                if (entityIterator == null) {
+                    Log.e(TAG, "EntityIterator is null");
+                    return contentValuesListMap;
+                }
+
+                if (!entityIterator.hasNext()) {
+                    Log.w(TAG, "Data does not exist. contactId: " + realContactId);
+                    return contentValuesListMap;
+                }
+
+                while (entityIterator.hasNext()) {
+                    Entity entity = entityIterator.next();
+                    for (NamedContentValues namedContentValues : entity.getSubValues()) {
+                        ContentValues contentValues = namedContentValues.values;
+                        String key = contentValues.getAsString(Data.MIMETYPE);
+                        if (key != null) {
+                            List<ContentValues> contentValuesList = contentValuesListMap.get(key);
+                            if (contentValuesList == null) {
+                                contentValuesList = new ArrayList<ContentValues>();
+                                contentValuesListMap.put(key, contentValuesList);
+                            }
+                            contentValuesList.add(contentValues);
+                        }
+                    }
+                }
+            } finally {
+                if (entityIterator != null) {
+                    entityIterator.close();
+                }
+            }
+            return contentValuesListMap;
+        }
     }
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java
index ec12040..5b44dba 100644
--- a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java
+++ b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java
@@ -43,6 +43,10 @@
     @VisibleForTesting
     static final int FPLMN_BYTE_SIZE = 3;
 
+    // ICCID used for tests by some OEMs
+    // TODO(b/159354974): Replace the constant here with UiccPortInfo.ICCID_REDACTED once ready
+    private static final String TEST_ICCID = "FFFFFFFFFFFFFFFFFFFF";
+
     // A table mapping from a number to a hex character for fast encoding hex strings.
     private static final char[] HEX_CHARS = {
             '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
@@ -923,6 +927,9 @@
      * Strip all the trailing 'F' characters of a string, e.g., an ICCID.
      */
     public static String stripTrailingFs(String s) {
+        if (TEST_ICCID.equals(s)) {
+            return s;
+        }
         return s == null ? null : s.replaceAll("(?i)f*$", "");
     }