Merge "Fix BlurUtils crash"
diff --git a/Android.bp b/Android.bp
index 1865a3d..58f6119 100644
--- a/Android.bp
+++ b/Android.bp
@@ -623,6 +623,7 @@
         "&& $(location soong_zip) -jar -o $(out) -C $(genDir)/$(in) -D $(genDir)/$(in)",
 
     srcs: [
+        ":ipconnectivity-proto-src",
         "core/proto/**/*.proto",
         "libs/incident/**/*.proto",
     ],
@@ -737,6 +738,7 @@
 java_library_host {
     name: "platformprotos",
     srcs: [
+        ":ipconnectivity-proto-src",
         "cmds/am/proto/instrumentation_data.proto",
         "cmds/statsd/src/**/*.proto",
         "core/proto/**/*.proto",
@@ -765,6 +767,7 @@
     ],
     sdk_version: "9",
     srcs: [
+        ":ipconnectivity-proto-src",
         "core/proto/**/*.proto",
         "libs/incident/proto/android/os/**/*.proto",
     ],
@@ -779,6 +782,7 @@
     },
 
     srcs: [
+        ":ipconnectivity-proto-src",
         "core/proto/**/*.proto",
         "libs/incident/proto/android/os/**/*.proto",
     ],
@@ -809,6 +813,7 @@
     ],
 
     srcs: [
+        ":ipconnectivity-proto-src",
         "core/proto/**/*.proto",
     ],
 }
@@ -1309,6 +1314,7 @@
     libs: [
         "framework-minus-apex",
         "unsupportedappusage",
+        "ike-stubs",
     ],
     static_libs: [
         "libphonenumber-platform",
diff --git a/apex/statsd/aidl/android/os/IStatsCompanionService.aidl b/apex/statsd/aidl/android/os/IStatsCompanionService.aidl
index 99b9d39..bdd1da7 100644
--- a/apex/statsd/aidl/android/os/IStatsCompanionService.aidl
+++ b/apex/statsd/aidl/android/os/IStatsCompanionService.aidl
@@ -16,9 +16,6 @@
 
 package android.os;
 
-import android.os.IPullAtomCallback;
-import android.os.StatsLogEventWrapper;
-
 /**
   * Binder interface to communicate with the Java-based statistics service helper.
   * {@hide}
@@ -62,9 +59,6 @@
     /** Cancel any alarm for the purpose of subscriber triggering. */
     oneway void cancelAlarmForSubscriberTriggering();
 
-    /** Pull the specified data. Results will be sent to statsd when complete. */
-    StatsLogEventWrapper[] pullData(int pullCode);
-
     /** Tells StatsCompaionService to grab the uid map snapshot and send it to statsd. */
     oneway void triggerUidSnapshot();
 }
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
index 018037c..bcbb5a1 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
@@ -714,87 +714,6 @@
         }
     }
 
-    private void pullDebugElapsedClock(int tagId,
-            long elapsedNanos, final long wallClockNanos, List<StatsLogEventWrapper> pulledData) {
-        final long elapsedMillis = SystemClock.elapsedRealtime();
-        final long clockDiffMillis = mDebugElapsedClockPreviousValue == 0
-                ? 0 : elapsedMillis - mDebugElapsedClockPreviousValue;
-
-        StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
-        e.writeLong(mDebugElapsedClockPullCount);
-        e.writeLong(elapsedMillis);
-        // Log it twice to be able to test multi-value aggregation from ValueMetric.
-        e.writeLong(elapsedMillis);
-        e.writeLong(clockDiffMillis);
-        e.writeInt(1 /* always set */);
-        pulledData.add(e);
-
-        if (mDebugElapsedClockPullCount % 2 == 1) {
-            StatsLogEventWrapper e2 = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
-            e2.writeLong(mDebugElapsedClockPullCount);
-            e2.writeLong(elapsedMillis);
-            // Log it twice to be able to test multi-value aggregation from ValueMetric.
-            e2.writeLong(elapsedMillis);
-            e2.writeLong(clockDiffMillis);
-            e2.writeInt(2 /* set on odd pulls */);
-            pulledData.add(e2);
-        }
-
-        mDebugElapsedClockPullCount++;
-        mDebugElapsedClockPreviousValue = elapsedMillis;
-    }
-
-    private void pullDebugFailingElapsedClock(int tagId,
-            long elapsedNanos, final long wallClockNanos, List<StatsLogEventWrapper> pulledData) {
-        StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
-        final long elapsedMillis = SystemClock.elapsedRealtime();
-        // Fails every 5 buckets.
-        if (mDebugFailingElapsedClockPullCount++ % 5 == 0) {
-            mDebugFailingElapsedClockPreviousValue = elapsedMillis;
-            throw new RuntimeException("Failing debug elapsed clock");
-        }
-
-        e.writeLong(mDebugFailingElapsedClockPullCount);
-        e.writeLong(elapsedMillis);
-        // Log it twice to be able to test multi-value aggregation from ValueMetric.
-        e.writeLong(elapsedMillis);
-        e.writeLong(mDebugFailingElapsedClockPreviousValue == 0
-                ? 0 : elapsedMillis - mDebugFailingElapsedClockPreviousValue);
-        mDebugFailingElapsedClockPreviousValue = elapsedMillis;
-        pulledData.add(e);
-    }
-
-    /**
-     * Pulls various data.
-     */
-    @Override // Binder call
-    public StatsLogEventWrapper[] pullData(int tagId) {
-        StatsCompanion.enforceStatsCompanionPermission(mContext);
-        if (DEBUG) {
-            Slog.d(TAG, "Pulling " + tagId);
-        }
-        List<StatsLogEventWrapper> ret = new ArrayList<>();
-        long elapsedNanos = SystemClock.elapsedRealtimeNanos();
-        long wallClockNanos = SystemClock.currentTimeMicro() * 1000L;
-        switch (tagId) {
-
-            case StatsLog.DEBUG_ELAPSED_CLOCK: {
-                pullDebugElapsedClock(tagId, elapsedNanos, wallClockNanos, ret);
-                break;
-            }
-
-            case StatsLog.DEBUG_FAILING_ELAPSED_CLOCK: {
-                pullDebugFailingElapsedClock(tagId, elapsedNanos, wallClockNanos, ret);
-                break;
-            }
-
-            default:
-                Slog.w(TAG, "No such tagId data as " + tagId);
-                return null;
-        }
-        return ret.toArray(new StatsLogEventWrapper[ret.size()]);
-    }
-
     @Override // Binder call
     public void statsdReady() {
         StatsCompanion.enforceStatsCompanionPermission(mContext);
diff --git a/api/current.txt b/api/current.txt
index 17f793c..5575675 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -39,6 +39,7 @@
     field public static final String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE";
     field public static final String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE";
     field public static final String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
+    field public static final String BIND_QUICK_ACCESS_WALLET_SERVICE = "android.permission.BIND_QUICK_ACCESS_WALLET_SERVICE";
     field public static final String BIND_QUICK_SETTINGS_TILE = "android.permission.BIND_QUICK_SETTINGS_TILE";
     field public static final String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
     field public static final String BIND_SCREENING_SERVICE = "android.permission.BIND_SCREENING_SERVICE";
@@ -6767,6 +6768,13 @@
     method public final android.os.IBinder onBind(android.content.Intent);
   }
 
+  public class DevicePolicyKeyguardService extends android.app.Service {
+    ctor public DevicePolicyKeyguardService();
+    method @Nullable public void dismiss();
+    method @Nullable public final android.os.IBinder onBind(@Nullable android.content.Intent);
+    method @Nullable public android.view.SurfaceControl onSurfaceReady(@Nullable android.os.IBinder);
+  }
+
   public class DevicePolicyManager {
     method public void addCrossProfileIntentFilter(@NonNull android.content.ComponentName, android.content.IntentFilter, int);
     method public boolean addCrossProfileWidgetProvider(@NonNull android.content.ComponentName, String);
@@ -6851,7 +6859,7 @@
     method public java.util.List<android.os.UserHandle> getSecondaryUsers(@NonNull android.content.ComponentName);
     method public CharSequence getShortSupportMessage(@NonNull android.content.ComponentName);
     method public CharSequence getStartUserSessionMessage(@NonNull android.content.ComponentName);
-    method public boolean getStorageEncryption(@Nullable android.content.ComponentName);
+    method @Deprecated public boolean getStorageEncryption(@Nullable android.content.ComponentName);
     method public int getStorageEncryptionStatus();
     method @Nullable public android.app.admin.SystemUpdatePolicy getSystemUpdatePolicy();
     method @Nullable public android.os.PersistableBundle getTransferOwnershipBundle();
@@ -6979,12 +6987,13 @@
     method public boolean setResetPasswordToken(android.content.ComponentName, byte[]);
     method public void setRestrictionsProvider(@NonNull android.content.ComponentName, @Nullable android.content.ComponentName);
     method public void setScreenCaptureDisabled(@NonNull android.content.ComponentName, boolean);
+    method public void setSecondaryLockscreenEnabled(@NonNull android.content.ComponentName, boolean);
     method public void setSecureSetting(@NonNull android.content.ComponentName, String, String);
     method public void setSecurityLoggingEnabled(@NonNull android.content.ComponentName, boolean);
     method public void setShortSupportMessage(@NonNull android.content.ComponentName, @Nullable CharSequence);
     method public void setStartUserSessionMessage(@NonNull android.content.ComponentName, @Nullable CharSequence);
     method public boolean setStatusBarDisabled(@NonNull android.content.ComponentName, boolean);
-    method public int setStorageEncryption(@NonNull android.content.ComponentName, boolean);
+    method @Deprecated public int setStorageEncryption(@NonNull android.content.ComponentName, boolean);
     method public void setSystemSetting(@NonNull android.content.ComponentName, @NonNull String, String);
     method public void setSystemUpdatePolicy(@NonNull android.content.ComponentName, android.app.admin.SystemUpdatePolicy);
     method public boolean setTime(@NonNull android.content.ComponentName, long);
@@ -7004,6 +7013,7 @@
     field public static final String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
     field public static final String ACTION_ADMIN_POLICY_COMPLIANCE = "android.app.action.ADMIN_POLICY_COMPLIANCE";
     field public static final String ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED = "android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED";
+    field public static final String ACTION_BIND_SECONDARY_LOCKSCREEN_SERVICE = "android.app.action.BIND_SECONDARY_LOCKSCREEN_SERVICE";
     field public static final String ACTION_DEVICE_ADMIN_SERVICE = "android.app.action.DEVICE_ADMIN_SERVICE";
     field public static final String ACTION_DEVICE_OWNER_CHANGED = "android.app.action.DEVICE_OWNER_CHANGED";
     field public static final String ACTION_GET_PROVISIONING_MODE = "android.app.action.GET_PROVISIONING_MODE";
@@ -11480,6 +11490,7 @@
     method @NonNull public android.graphics.drawable.Drawable getProfileSwitchingIconDrawable(@NonNull android.os.UserHandle);
     method @NonNull public CharSequence getProfileSwitchingLabel(@NonNull android.os.UserHandle);
     method @NonNull public java.util.List<android.os.UserHandle> getTargetUserProfiles();
+    method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_PROFILES, "android.permission.INTERACT_ACROSS_USERS"}) public void startActivity(@NonNull android.content.Intent, @NonNull android.os.UserHandle);
     method public void startMainActivity(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle);
     field public static final String ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED = "android.content.pm.action.CAN_INTERACT_ACROSS_PROFILES_CHANGED";
   }
@@ -11925,6 +11936,7 @@
     method public boolean hasSigningCertificate(int, @NonNull byte[], int);
     method public abstract boolean hasSystemFeature(@NonNull String);
     method public abstract boolean hasSystemFeature(@NonNull String, int);
+    method public boolean isDefaultApplicationIcon(@NonNull android.graphics.drawable.Drawable);
     method public boolean isDeviceUpgrading();
     method public abstract boolean isInstantApp();
     method public abstract boolean isInstantApp(@NonNull String);
@@ -11987,6 +11999,7 @@
     field public static final String FEATURE_COMPANION_DEVICE_SETUP = "android.software.companion_device_setup";
     field public static final String FEATURE_CONNECTION_SERVICE = "android.software.connectionservice";
     field public static final String FEATURE_CONSUMER_IR = "android.hardware.consumerir";
+    field public static final String FEATURE_CONTEXTHUB = "android.hardware.context_hub";
     field public static final String FEATURE_DEVICE_ADMIN = "android.software.device_admin";
     field public static final String FEATURE_EMBEDDED = "android.hardware.type.embedded";
     field public static final String FEATURE_ETHERNET = "android.hardware.ethernet";
@@ -17039,6 +17052,8 @@
     method public abstract int setRepeatingRequest(@NonNull android.hardware.camera2.CaptureRequest, @Nullable android.hardware.camera2.CameraCaptureSession.CaptureCallback, @Nullable android.os.Handler) throws android.hardware.camera2.CameraAccessException;
     method public int setSingleRepeatingRequest(@NonNull android.hardware.camera2.CaptureRequest, @NonNull java.util.concurrent.Executor, @NonNull android.hardware.camera2.CameraCaptureSession.CaptureCallback) throws android.hardware.camera2.CameraAccessException;
     method public abstract void stopRepeating() throws android.hardware.camera2.CameraAccessException;
+    method public boolean supportsOfflineProcessing(@NonNull android.view.Surface);
+    method @Nullable public android.hardware.camera2.CameraOfflineSession switchToOffline(@NonNull java.util.Collection<android.view.Surface>, @NonNull java.util.concurrent.Executor, @NonNull android.hardware.camera2.CameraOfflineSession.CameraOfflineSessionCallback) throws android.hardware.camera2.CameraAccessException;
     method public void updateOutputConfiguration(android.hardware.camera2.params.OutputConfiguration) throws android.hardware.camera2.CameraAccessException;
   }
 
@@ -17463,6 +17478,20 @@
     field public static final int TONEMAP_PRESET_CURVE_SRGB = 0; // 0x0
   }
 
+  public abstract class CameraOfflineSession extends android.hardware.camera2.CameraCaptureSession {
+    ctor public CameraOfflineSession();
+  }
+
+  public abstract static class CameraOfflineSession.CameraOfflineSessionCallback {
+    ctor public CameraOfflineSession.CameraOfflineSessionCallback();
+    method public abstract void onClosed(@NonNull android.hardware.camera2.CameraOfflineSession);
+    method public abstract void onError(@NonNull android.hardware.camera2.CameraOfflineSession, int);
+    method public abstract void onIdle(@NonNull android.hardware.camera2.CameraOfflineSession);
+    method public abstract void onReady(@NonNull android.hardware.camera2.CameraOfflineSession);
+    method public abstract void onSwitchFailed(@NonNull android.hardware.camera2.CameraOfflineSession);
+    field public static final int STATUS_INTERNAL_ERROR = 0; // 0x0
+  }
+
   public class CaptureFailure {
     method public long getFrameNumber();
     method @Nullable public String getPhysicalCameraId();
@@ -24116,6 +24145,37 @@
     method public void onAudioFocusChange(int);
   }
 
+  public final class AudioMetadata {
+    method @NonNull public static android.media.AudioMetadata.Map createMap();
+  }
+
+  public static class AudioMetadata.Format {
+    field @NonNull public static final android.media.AudioMetadata.Key<java.lang.Boolean> KEY_ATMOS_PRESENT;
+    field @NonNull public static final android.media.AudioMetadata.Key<java.lang.Integer> KEY_AUDIO_ENCODING;
+    field @NonNull public static final android.media.AudioMetadata.Key<java.lang.Integer> KEY_BIT_RATE;
+    field @NonNull public static final android.media.AudioMetadata.Key<java.lang.Integer> KEY_BIT_WIDTH;
+    field @NonNull public static final android.media.AudioMetadata.Key<java.lang.Integer> KEY_CHANNEL_MASK;
+    field @NonNull public static final android.media.AudioMetadata.Key<java.lang.String> KEY_MIME;
+    field @NonNull public static final android.media.AudioMetadata.Key<java.lang.Integer> KEY_SAMPLE_RATE;
+  }
+
+  public static interface AudioMetadata.Key<T> {
+    method @NonNull public String getName();
+    method @NonNull public Class<T> getValueClass();
+  }
+
+  public static interface AudioMetadata.Map extends android.media.AudioMetadata.ReadMap {
+    method @Nullable public <T> T remove(@NonNull android.media.AudioMetadata.Key<T>);
+    method @Nullable public <T> T set(@NonNull android.media.AudioMetadata.Key<T>, @NonNull T);
+  }
+
+  public static interface AudioMetadata.ReadMap {
+    method public <T> boolean containsKey(@NonNull android.media.AudioMetadata.Key<T>);
+    method @NonNull public android.media.AudioMetadata.Map dup();
+    method @Nullable public <T> T get(@NonNull android.media.AudioMetadata.Key<T>);
+    method public int size();
+  }
+
   public final class AudioPlaybackCaptureConfiguration {
     method @NonNull public int[] getExcludeUids();
     method @NonNull public int[] getExcludeUsages();
@@ -24301,6 +24361,7 @@
     ctor @Deprecated public AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
     ctor @Deprecated public AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
     ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException;
+    method public void addOnCodecFormatChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioTrack.OnCodecFormatChangedListener);
     method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
     method @Deprecated public void addOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener, android.os.Handler);
     method public int attachAuxEffect(int);
@@ -24344,6 +24405,7 @@
     method public void registerStreamEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioTrack.StreamEventCallback);
     method public void release();
     method public int reloadStaticData();
+    method public void removeOnCodecFormatChangedListener(@NonNull android.media.AudioTrack.OnCodecFormatChangedListener);
     method public void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener);
     method @Deprecated public void removeOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener);
     method public int setAuxEffectSendLevel(@FloatRange(from=0.0) float);
@@ -24417,6 +24479,10 @@
     field public static final String USAGE = "android.media.audiotrack.usage";
   }
 
+  public static interface AudioTrack.OnCodecFormatChangedListener {
+    method public void onCodecFormatChanged(@NonNull android.media.AudioTrack, @Nullable android.media.AudioMetadata.ReadMap);
+  }
+
   public static interface AudioTrack.OnPlaybackPositionUpdateListener {
     method public void onMarkerReached(android.media.AudioTrack);
     method public void onPeriodicNotification(android.media.AudioTrack);
@@ -29866,6 +29932,7 @@
   }
 
   @Deprecated public class NetworkInfo implements android.os.Parcelable {
+    ctor @Deprecated public NetworkInfo(int, int, @Nullable String, @Nullable String);
     method @Deprecated public int describeContents();
     method @Deprecated @NonNull public android.net.NetworkInfo.DetailedState getDetailedState();
     method @Deprecated public String getExtraInfo();
@@ -29880,6 +29947,7 @@
     method @Deprecated public boolean isConnectedOrConnecting();
     method @Deprecated public boolean isFailover();
     method @Deprecated public boolean isRoaming();
+    method @Deprecated public void setDetailedState(@NonNull android.net.NetworkInfo.DetailedState, @Nullable String, @Nullable String);
     method @Deprecated public void writeToParcel(android.os.Parcel, int);
     field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkInfo> CREATOR;
   }
@@ -31794,7 +31862,7 @@
     method public boolean isLciSubelementValid();
     method public boolean isZaxisSubelementValid();
     method @Nullable public android.location.Address toCivicLocationAddress();
-    method @Nullable public android.util.SparseArray toCivicLocationSparseArray();
+    method @Nullable public android.util.SparseArray<java.lang.String> toCivicLocationSparseArray();
     method @NonNull public android.location.Location toLocation();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int ALTITUDE_FLOORS = 2; // 0x2
@@ -40032,6 +40100,7 @@
     field public static final String ACTION_PRINT_SETTINGS = "android.settings.ACTION_PRINT_SETTINGS";
     field public static final String ACTION_PRIVACY_SETTINGS = "android.settings.PRIVACY_SETTINGS";
     field public static final String ACTION_PROCESS_WIFI_EASY_CONNECT_URI = "android.settings.PROCESS_WIFI_EASY_CONNECT_URI";
+    field public static final String ACTION_QUICK_ACCESS_WALLET_SETTINGS = "android.settings.QUICK_ACCESS_WALLET_SETTINGS";
     field public static final String ACTION_QUICK_LAUNCH_SETTINGS = "android.settings.QUICK_LAUNCH_SETTINGS";
     field public static final String ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
     field public static final String ACTION_REQUEST_SET_AUTOFILL_SERVICE = "android.settings.REQUEST_SET_AUTOFILL_SERVICE";
@@ -42218,7 +42287,6 @@
   }
 
   public abstract class WritableIdentityCredential {
-    ctor public WritableIdentityCredential();
     method @NonNull public abstract java.util.Collection<java.security.cert.X509Certificate> getCredentialKeyCertificateChain(@NonNull byte[]);
     method @NonNull public abstract byte[] personalize(@NonNull android.security.identity.PersonalizationData);
   }
@@ -43208,6 +43276,94 @@
 
 }
 
+package android.service.quickaccesswallet {
+
+  public final class GetWalletCardsCallback {
+    method public void onFailure(@NonNull android.service.quickaccesswallet.GetWalletCardsError);
+    method public void onSuccess(@NonNull android.service.quickaccesswallet.GetWalletCardsResponse);
+  }
+
+  public final class GetWalletCardsError implements android.os.Parcelable {
+    ctor public GetWalletCardsError(@Nullable android.graphics.drawable.Icon, @Nullable CharSequence);
+    method public int describeContents();
+    method @Nullable public android.graphics.drawable.Icon getIcon();
+    method @Nullable public CharSequence getMessage();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.service.quickaccesswallet.GetWalletCardsError> CREATOR;
+  }
+
+  public final class GetWalletCardsRequest implements android.os.Parcelable {
+    ctor public GetWalletCardsRequest(int, int, int, int);
+    method public int describeContents();
+    method public int getCardHeightPx();
+    method public int getCardWidthPx();
+    method public int getIconSizePx();
+    method public int getMaxCards();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.service.quickaccesswallet.GetWalletCardsRequest> CREATOR;
+  }
+
+  public final class GetWalletCardsResponse implements android.os.Parcelable {
+    ctor public GetWalletCardsResponse(@NonNull java.util.List<android.service.quickaccesswallet.WalletCard>, int);
+    method public int describeContents();
+    method public int getSelectedIndex();
+    method @NonNull public java.util.List<android.service.quickaccesswallet.WalletCard> getWalletCards();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.service.quickaccesswallet.GetWalletCardsResponse> CREATOR;
+  }
+
+  public abstract class QuickAccessWalletService extends android.app.Service {
+    ctor public QuickAccessWalletService();
+    method @Nullable public android.os.IBinder onBind(@NonNull android.content.Intent);
+    method public abstract void onWalletCardSelected(@NonNull android.service.quickaccesswallet.SelectWalletCardRequest);
+    method public abstract void onWalletCardsRequested(@NonNull android.service.quickaccesswallet.GetWalletCardsRequest, @NonNull android.service.quickaccesswallet.GetWalletCardsCallback);
+    method public abstract void onWalletDismissed();
+    method public final void sendWalletServiceEvent(@NonNull android.service.quickaccesswallet.WalletServiceEvent);
+    field public static final String ACTION_DISMISS_WALLET = "android.service.quickaccesswallet.action.DISMISS_WALLET";
+    field public static final String ACTION_VIEW_WALLET = "android.service.quickaccesswallet.action.VIEW_WALLET";
+    field public static final String ACTION_VIEW_WALLET_SETTINGS = "android.service.quickaccesswallet.action.VIEW_WALLET_SETTINGS";
+    field public static final String SERVICE_INTERFACE = "android.service.quickaccesswallet.QuickAccessWalletService";
+    field public static final String SERVICE_META_DATA = "android.quickaccesswallet";
+  }
+
+  public final class SelectWalletCardRequest implements android.os.Parcelable {
+    ctor public SelectWalletCardRequest(@NonNull String);
+    method public int describeContents();
+    method @NonNull public String getCardId();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.service.quickaccesswallet.SelectWalletCardRequest> CREATOR;
+  }
+
+  public final class WalletCard implements android.os.Parcelable {
+    method public int describeContents();
+    method @Nullable public android.graphics.drawable.Icon getCardIcon();
+    method @NonNull public String getCardId();
+    method @NonNull public android.graphics.drawable.Icon getCardImage();
+    method @Nullable public CharSequence getCardLabel();
+    method @NonNull public CharSequence getContentDescription();
+    method @NonNull public android.app.PendingIntent getPendingIntent();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.service.quickaccesswallet.WalletCard> CREATOR;
+  }
+
+  public static final class WalletCard.Builder {
+    ctor public WalletCard.Builder(@NonNull String, @NonNull android.graphics.drawable.Icon, @NonNull CharSequence, @NonNull android.app.PendingIntent);
+    method @NonNull public android.service.quickaccesswallet.WalletCard build();
+    method @NonNull public android.service.quickaccesswallet.WalletCard.Builder setCardIcon(@Nullable android.graphics.drawable.Icon);
+    method @NonNull public android.service.quickaccesswallet.WalletCard.Builder setCardLabel(@Nullable CharSequence);
+  }
+
+  public final class WalletServiceEvent implements android.os.Parcelable {
+    ctor public WalletServiceEvent(int);
+    method public int describeContents();
+    method public int getEventType();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.service.quickaccesswallet.WalletServiceEvent> CREATOR;
+    field public static final int TYPE_NFC_PAYMENT_STARTED = 1; // 0x1
+  }
+
+}
+
 package android.service.quicksettings {
 
   public final class Tile implements android.os.Parcelable {
@@ -45942,6 +46098,59 @@
     field public static final String KEY_WIFI_OFF_DEFERRING_TIME_INT = "ims.wifi_off_deferring_time_int";
   }
 
+  public static final class CarrierConfigManager.Iwlan {
+    field public static final int AUTHENTICATION_METHOD_CERT = 1; // 0x1
+    field public static final int AUTHENTICATION_METHOD_EAP_ONLY = 0; // 0x0
+    field public static final int DH_GROUP_1024_BIT_MODP = 2; // 0x2
+    field public static final int DH_GROUP_2048_BIT_MODP = 14; // 0xe
+    field public static final int DH_GROUP_NONE = 0; // 0x0
+    field public static final int ENCRYPTION_ALGORITHM_3DES = 3; // 0x3
+    field public static final int ENCRYPTION_ALGORITHM_AES_CBC = 12; // 0xc
+    field public static final int ENCRYPTION_ALGORITHM_AES_GCM_12 = 19; // 0x13
+    field public static final int ENCRYPTION_ALGORITHM_AES_GCM_16 = 20; // 0x14
+    field public static final int ENCRYPTION_ALGORITHM_AES_GCM_8 = 18; // 0x12
+    field public static final int EPDG_ADDRESS_PCO = 2; // 0x2
+    field public static final int EPDG_ADDRESS_PLMN = 1; // 0x1
+    field public static final int EPDG_ADDRESS_STATIC = 0; // 0x0
+    field public static final int INTEGRITY_ALGORITHM_AES_XCBC_96 = 5; // 0x5
+    field public static final int INTEGRITY_ALGORITHM_HMAC_SHA1_96 = 2; // 0x2
+    field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_256_128 = 12; // 0xc
+    field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_384_192 = 13; // 0xd
+    field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_512_256 = 14; // 0xe
+    field public static final int INTEGRITY_ALGORITHM_NONE = 0; // 0x0
+    field public static final String KEY_CHILD_SA_REKEY_HARD_TIMER_SEC_INT = "iwlan.child_sa_rekey_hard_timer_sec_int";
+    field public static final String KEY_CHILD_SA_REKEY_SOFT_TIMER_SEC_INT = "iwlan.child_sa_rekey_soft_timer_sec_int";
+    field public static final String KEY_CHILD_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY = "iwlan.child_session_aes_cbc_key_size_int_array";
+    field public static final String KEY_CHILD_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY = "iwlan.child_encryption_aes_ctr_key_size_int_array";
+    field public static final String KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY = "iwlan.diffie_hellman_groups_int_array";
+    field public static final String KEY_DPD_TIMER_SEC_INT = "iwlan.dpd_timer_sec_int";
+    field public static final String KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY = "iwlan.epdg_address_priority_int_array";
+    field public static final String KEY_EPDG_AUTHENTICATION_METHOD_INT = "iwlan.epdg_authentication_method_int";
+    field public static final String KEY_EPDG_STATIC_ADDRESS_ROAMING_STRING = "iwlan.epdg_static_address_roaming_string";
+    field public static final String KEY_EPDG_STATIC_ADDRESS_STRING = "iwlan.epdg_static_address_string";
+    field public static final String KEY_IKE_FRAGMENTATION_ENABLED_BOOL = "iwlan.ike_fragmentation_enabled_bool";
+    field public static final String KEY_IKE_REKEY_HARD_TIMER_SEC_INT = "iwlan.ike_rekey_hard_timer_in_sec";
+    field public static final String KEY_IKE_REKEY_SOFT_TIMER_SEC_INT = "iwlan.ike_rekey_soft_timer_sec_int";
+    field public static final String KEY_IKE_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY = "iwlan.ike_session_encryption_aes_cbc_key_size_int_array";
+    field public static final String KEY_IKE_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY = "iwlan.ike_session_aes_ctr_key_size_int_array";
+    field public static final int KEY_LEN_AES_128 = 128; // 0x80
+    field public static final int KEY_LEN_AES_192 = 192; // 0xc0
+    field public static final int KEY_LEN_AES_256 = 256; // 0x100
+    field public static final int KEY_LEN_UNUSED = 0; // 0x0
+    field public static final String KEY_MAX_RETRIES_INT = "iwlan.max_retries_int";
+    field public static final String KEY_MCC_MNCS_STRING_ARRAY = "iwlan.mcc_mncs_string_array";
+    field public static final String KEY_NATT_ENABLED_BOOL = "iwlan.natt_enabled_bool";
+    field public static final String KEY_NATT_KEEP_ALIVE_TIMER_SEC_INT = "iwlan.natt_keep_alive_timer_sec_int";
+    field public static final String KEY_PREFIX = "iwlan.";
+    field public static final String KEY_RETRANSMIT_TIMER_SEC_INT = "iwlan.retransmit_timer_sec_int";
+    field public static final String KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY = "iwlan.supported_child_session_encryption_algorithms_int_array";
+    field public static final String KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY = "iwlan.supported_ike_session_encryption_algorithms_int_array";
+    field public static final String KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY = "iwlan.supported_integrity_algorithms_int_array";
+    field public static final String KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY = "iwlan.supported_prf_algorithms_int_array";
+    field public static final int PSEUDORANDOM_FUNCTION_AES128_XCBC = 4; // 0x4
+    field public static final int PSEUDORANDOM_FUNCTION_HMAC_SHA1 = 2; // 0x2
+  }
+
   public abstract class CellIdentity implements android.os.Parcelable {
     method public int describeContents();
     method @Nullable public CharSequence getOperatorAlphaLong();
@@ -46332,8 +46541,32 @@
 
   public final class PhoneCapability implements android.os.Parcelable {
     method public int describeContents();
+    method @NonNull public java.util.List<java.lang.Integer> getBands(int);
+    method @NonNull public java.util.List<java.util.List<java.lang.Long>> getConcurrentFeaturesSupport();
+    method @NonNull public java.util.List<java.lang.String> getLogicalModemUuids();
+    method public int getMaxActiveDedicatedBearers();
+    method public int getMaxActiveInternetData();
+    method public int getMaxActivePsVoice();
+    method public long getPsDataConnectionLingerTimeMillis();
+    method @NonNull public java.util.List<android.telephony.SimSlotCapability> getSimSlotCapabilities();
+    method public long getSupportedRats();
+    method public int getUeCategory(boolean, int);
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PhoneCapability> CREATOR;
+    field public static final long MODEM_FEATURE_3GPP2_REG = 1L; // 0x1L
+    field public static final long MODEM_FEATURE_3GPP_REG = 2L; // 0x2L
+    field public static final long MODEM_FEATURE_CDMA2000_EHRPD_REG = 4L; // 0x4L
+    field public static final long MODEM_FEATURE_CSIM = 8192L; // 0x2000L
+    field public static final long MODEM_FEATURE_CS_VOICE_SESSION = 512L; // 0x200L
+    field public static final long MODEM_FEATURE_DEDICATED_BEARER = 2048L; // 0x800L
+    field public static final long MODEM_FEATURE_EUTRAN_REG = 32L; // 0x20L
+    field public static final long MODEM_FEATURE_EUTRA_NR_DUAL_CONNECTIVITY_REG = 128L; // 0x80L
+    field public static final long MODEM_FEATURE_GERAN_REG = 8L; // 0x8L
+    field public static final long MODEM_FEATURE_INTERACTIVE_DATA_SESSION = 1024L; // 0x400L
+    field public static final long MODEM_FEATURE_NETWORK_SCAN = 4096L; // 0x1000L
+    field public static final long MODEM_FEATURE_NGRAN_REG = 64L; // 0x40L
+    field public static final long MODEM_FEATURE_PS_VOICE_REG = 256L; // 0x100L
+    field public static final long MODEM_FEATURE_UTRAN_REG = 16L; // 0x10L
   }
 
   public class PhoneNumberFormattingTextWatcher implements android.text.TextWatcher {
@@ -46436,7 +46669,7 @@
     field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_IMS_CALL_DISCONNECT_CAUSES = 134217728; // 0x8000000
     field public static final int LISTEN_MESSAGE_WAITING_INDICATOR = 4; // 0x4
     field public static final int LISTEN_NONE = 0; // 0x0
-    field @RequiresPermission("android.permission.MODIFY_PHONE_STATE") public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 4096; // 0x1000
+    field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 4096; // 0x1000
     field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int LISTEN_REGISTRATION_FAILURE = 1073741824; // 0x40000000
     field public static final int LISTEN_SERVICE_STATE = 1; // 0x1
     field @Deprecated public static final int LISTEN_SIGNAL_STRENGTH = 2; // 0x2
@@ -46520,6 +46753,18 @@
     field public static final int INVALID = 2147483647; // 0x7fffffff
   }
 
+  public final class SimSlotCapability implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getPhysicalSlotIndex();
+    method public int getSlotType();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SimSlotCapability> CREATOR;
+    field public static final int SLOT_TYPE_EUICC = 3; // 0x3
+    field public static final int SLOT_TYPE_IUICC = 2; // 0x2
+    field public static final int SLOT_TYPE_SOFT_SIM = 4; // 0x4
+    field public static final int SLOT_TYPE_UICC = 1; // 0x1
+  }
+
   public final class SmsManager {
     method public String createAppSpecificSmsToken(android.app.PendingIntent);
     method @Nullable public String createAppSpecificSmsTokenWithPackageInfo(@Nullable String, @NonNull android.app.PendingIntent);
@@ -46872,8 +47117,10 @@
     method public String getNetworkCountryIso();
     method public String getNetworkOperator();
     method public String getNetworkOperatorName();
+    method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public int getNetworkSelectionMode();
     method public String getNetworkSpecifier();
     method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getNetworkType();
+    method @Nullable @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public android.telephony.PhoneCapability getPhoneCapability();
     method @Deprecated public int getPhoneCount();
     method public int getPhoneType();
     method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PHONE_STATE}) public int getPreferredOpportunisticDataSubscription();
@@ -47006,6 +47253,9 @@
     field public static final int MULTISIM_ALLOWED = 0; // 0x0
     field public static final int MULTISIM_NOT_SUPPORTED_BY_CARRIER = 2; // 0x2
     field public static final int MULTISIM_NOT_SUPPORTED_BY_HARDWARE = 1; // 0x1
+    field public static final int NETWORK_SELECTION_MODE_AUTO = 1; // 0x1
+    field public static final int NETWORK_SELECTION_MODE_MANUAL = 2; // 0x2
+    field public static final int NETWORK_SELECTION_MODE_UNKNOWN = 0; // 0x0
     field public static final int NETWORK_TYPE_1xRTT = 7; // 0x7
     field public static final int NETWORK_TYPE_CDMA = 4; // 0x4
     field public static final int NETWORK_TYPE_EDGE = 2; // 0x2
diff --git a/api/module-app-current.txt b/api/module-app-current.txt
index db774ef..dadbd79 100644
--- a/api/module-app-current.txt
+++ b/api/module-app-current.txt
@@ -9,6 +9,10 @@
 
 package android.provider {
 
+  public final class DocumentsContract {
+    method @NonNull public static android.net.Uri buildDocumentUriAsUser(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
+  }
+
   public static final class Settings.Global extends android.provider.Settings.NameValueTable {
     field public static final String COMMON_CRITERIA_MODE = "common_criteria_mode";
   }
diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt
index 1cb1c20..6f4a27e 100644
--- a/api/module-lib-current.txt
+++ b/api/module-lib-current.txt
@@ -118,10 +118,32 @@
   }
 
   public final class TimeZoneFinder {
+    method @Nullable public String getIanaVersion();
     method @NonNull public static android.timezone.TimeZoneFinder getInstance();
     method @Nullable public android.timezone.CountryTimeZones lookupCountryTimeZones(@NonNull String);
   }
 
+  public final class TzDataSetVersion {
+    method public static int currentFormatMajorVersion();
+    method public static int currentFormatMinorVersion();
+    method public int getFormatMajorVersion();
+    method public int getFormatMinorVersion();
+    method public int getRevision();
+    method @NonNull public String getRulesVersion();
+    method public static boolean isCompatibleWithThisDevice(android.timezone.TzDataSetVersion);
+    method @NonNull public static android.timezone.TzDataSetVersion read() throws java.io.IOException, android.timezone.TzDataSetVersion.TzDataSetException;
+  }
+
+  public static class TzDataSetVersion.TzDataSetException extends java.lang.Exception {
+    ctor public TzDataSetVersion.TzDataSetException(String);
+    ctor public TzDataSetVersion.TzDataSetException(String, Throwable);
+  }
+
+  public final class ZoneInfoDb {
+    method @NonNull public static android.timezone.ZoneInfoDb getInstance();
+    method @NonNull public String getVersion();
+  }
+
 }
 
 package android.util {
diff --git a/api/system-current.txt b/api/system-current.txt
index 165abc8..327f642 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -845,6 +845,7 @@
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isDeviceProvisioned();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isDeviceProvisioningConfigApplied();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isManagedKiosk();
+    method public boolean isSecondaryLockscreenEnabled(int);
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isUnattendedManagedKiosk();
     method @RequiresPermission("android.permission.NOTIFY_PENDING_SYSTEM_UPDATE") public void notifyPendingSystemUpdate(long);
     method @RequiresPermission("android.permission.NOTIFY_PENDING_SYSTEM_UPDATE") public void notifyPendingSystemUpdate(long, boolean);
@@ -1627,10 +1628,14 @@
   }
 
   public interface BluetoothProfile {
+    field public static final int A2DP_SINK = 11; // 0xb
+    field public static final int AVRCP_CONTROLLER = 12; // 0xc
     field public static final int CONNECTION_POLICY_ALLOWED = 100; // 0x64
     field public static final int CONNECTION_POLICY_FORBIDDEN = 0; // 0x0
     field public static final int CONNECTION_POLICY_UNKNOWN = -1; // 0xffffffff
+    field public static final int HEADSET_CLIENT = 16; // 0x10
     field public static final int PAN = 5; // 0x5
+    field public static final int PBAP_CLIENT = 17; // 0x11
     field @Deprecated public static final int PRIORITY_OFF = 0; // 0x0
     field @Deprecated public static final int PRIORITY_ON = 100; // 0x64
   }
@@ -1713,6 +1718,13 @@
 
 package android.content {
 
+  public class ApexContext {
+    method @NonNull public static android.content.ApexContext getApexContext(@NonNull String);
+    method @NonNull public java.io.File getCredentialProtectedDataDirForUser(@NonNull android.os.UserHandle);
+    method @NonNull public java.io.File getDeviceProtectedDataDir();
+    method @NonNull public java.io.File getDeviceProtectedDataDirForUser(@NonNull android.os.UserHandle);
+  }
+
   public abstract class BroadcastReceiver {
     method @NonNull public final android.os.UserHandle getSendingUser();
   }
@@ -2286,6 +2298,7 @@
     field public static final int MATCH_ANY_USER = 4194304; // 0x400000
     field public static final int MATCH_FACTORY_ONLY = 2097152; // 0x200000
     field public static final int MATCH_INSTANT = 8388608; // 0x800000
+    field public static final int MODULE_APEX_NAME = 1; // 0x1
     field public static final int RESTRICTION_HIDE_FROM_SUGGESTIONS = 1; // 0x1
     field public static final int RESTRICTION_HIDE_NOTIFICATIONS = 2; // 0x2
     field public static final int RESTRICTION_NONE = 0; // 0x0
@@ -2434,6 +2447,15 @@
 
 }
 
+package android.debug {
+
+  public class AdbManager {
+    method @RequiresPermission(android.Manifest.permission.MANAGE_DEBUGGING) public boolean isAdbWifiQrSupported();
+    method @RequiresPermission(android.Manifest.permission.MANAGE_DEBUGGING) public boolean isAdbWifiSupported();
+  }
+
+}
+
 package android.hardware {
 
   public final class Sensor {
@@ -4097,17 +4119,24 @@
     method public int getAllFlags();
     method public android.os.Bundle getBundle();
     method public int getCapturePreset();
+    method public int getSystemUsage();
+    method public static boolean isSystemUsage(int);
     field public static final int FLAG_BEACON = 8; // 0x8
     field public static final int FLAG_BYPASS_INTERRUPTION_POLICY = 64; // 0x40
     field public static final int FLAG_BYPASS_MUTE = 128; // 0x80
     field public static final int FLAG_HW_HOTWORD = 32; // 0x20
-    field @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public static final int USAGE_CALL_ASSISTANT = 17; // 0x11
+    field @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static final int USAGE_ANNOUNCEMENT = 1003; // 0x3eb
+    field @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.MODIFY_AUDIO_ROUTING}) public static final int USAGE_CALL_ASSISTANT = 17; // 0x11
+    field @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static final int USAGE_EMERGENCY = 1000; // 0x3e8
+    field @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static final int USAGE_SAFETY = 1001; // 0x3e9
+    field @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static final int USAGE_VEHICLE_STATUS = 1002; // 0x3ea
   }
 
   public static class AudioAttributes.Builder {
     method public android.media.AudioAttributes.Builder addBundle(@NonNull android.os.Bundle);
     method public android.media.AudioAttributes.Builder setCapturePreset(int);
     method public android.media.AudioAttributes.Builder setInternalCapturePreset(int);
+    method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioAttributes.Builder setSystemUsage(int);
   }
 
   public final class AudioDeviceAddress implements android.os.Parcelable {
@@ -4158,6 +4187,7 @@
     method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMaxVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
     method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMinVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
     method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioDeviceAddress getPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy);
+    method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int[] getSupportedSystemUsages();
     method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
     method public boolean isAudioServerRunning();
     method public boolean isHdmiSystemAudioSupported();
@@ -4170,6 +4200,7 @@
     method public void setAudioServerStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.AudioServerStateCallback);
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setFocusRequestResult(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy, @NonNull android.media.AudioDeviceAddress);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setSupportedSystemUsages(@NonNull int[]);
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setVolumeIndexForAttributes(@NonNull android.media.AudioAttributes, int, int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void unregisterAudioPolicy(@NonNull android.media.audiopolicy.AudioPolicy);
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void unregisterAudioPolicyAsync(@NonNull android.media.audiopolicy.AudioPolicy);
@@ -4584,7 +4615,8 @@
   }
 
   public final class TvInputManager {
-    method @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE) public android.media.tv.TvInputManager.Hardware acquireTvInputHardware(int, android.media.tv.TvInputInfo, android.media.tv.TvInputManager.HardwareCallback);
+    method @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE) public android.media.tv.TvInputManager.Hardware acquireTvInputHardware(int, @NonNull android.media.tv.TvInputInfo, @NonNull android.media.tv.TvInputManager.HardwareCallback);
+    method @Nullable @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE) public android.media.tv.TvInputManager.Hardware acquireTvInputHardware(int, @NonNull android.media.tv.TvInputInfo, @NonNull android.media.tv.TvInputManager.HardwareCallback, @Nullable String, int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) public void addBlockedRating(@NonNull android.media.tv.TvContentRating);
     method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public boolean captureFrame(String, android.view.Surface, android.media.tv.TvStreamConfig);
     method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public java.util.List<android.media.tv.TvStreamConfig> getAvailableTvStreamConfigList(String);
@@ -4727,10 +4759,18 @@
     method public void onEvent(int);
   }
 
-  public final class Tuner implements java.lang.AutoCloseable {
-    ctor public Tuner(@NonNull android.content.Context);
+  public class Tuner implements java.lang.AutoCloseable {
+    ctor @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public Tuner(@NonNull android.content.Context, @NonNull String, int, @Nullable android.media.tv.tuner.Tuner.OnResourceLostListener);
     method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void clearOnTuneEventListener();
-    method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.Tuner.Descrambler openDescrambler();
+    method public void close();
+    method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int connectCiCam(int);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int disconnectCiCam();
+    method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int getAvSyncHwId(@NonNull android.media.tv.tuner.filter.Filter);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public long getAvSyncTime(int);
+    method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public static android.media.tv.tuner.DemuxCapabilities getDemuxCapabilities(@NonNull android.content.Context);
+    method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.frontend.FrontendInfo getFrontendInfo();
+    method @Nullable public android.media.tv.tuner.frontend.FrontendStatus getFrontendStatus(@NonNull int[]);
+    method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.Descrambler openDescrambler();
     method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.dvr.DvrPlayback openDvrPlayback(long, @Nullable java.util.concurrent.Executor, @Nullable android.media.tv.tuner.dvr.OnPlaybackStatusChangedListener);
     method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.dvr.DvrRecorder openDvrRecorder(long, @Nullable java.util.concurrent.Executor, @Nullable android.media.tv.tuner.dvr.OnRecordStatusChangedListener);
     method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.filter.Filter openFilter(int, int, long, @Nullable java.util.concurrent.Executor, @Nullable android.media.tv.tuner.filter.FilterCallback);
@@ -4738,16 +4778,21 @@
     method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.Lnb openLnbByName(@Nullable String, @Nullable java.util.concurrent.Executor, @NonNull android.media.tv.tuner.LnbCallback);
     method @Nullable public android.media.tv.tuner.filter.TimeFilter openTimeFilter();
     method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int scan(@NonNull android.media.tv.tuner.frontend.FrontendSettings, int, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.frontend.ScanCallback);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int setLna(boolean);
     method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void setOnTuneEventListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.frontend.OnTuneEventListener);
+    method public void shareFrontendFromTuner(@NonNull android.media.tv.tuner.Tuner);
     method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int stopScan();
     method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int stopTune();
     method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int tune(@NonNull android.media.tv.tuner.frontend.FrontendSettings);
   }
 
-  public class Tuner.Descrambler {
+  public static interface Tuner.OnResourceLostListener {
+    method public void onResourceLost(@NonNull android.media.tv.tuner.Tuner);
   }
 
   public final class TunerConstants {
+    field public static final int INVALID_STREAM_ID = -1; // 0xffffffff
+    field public static final int INVALID_TS_PID = -1; // 0xffffffff
     field public static final int RESULT_INVALID_ARGUMENT = 4; // 0x4
     field public static final int RESULT_INVALID_STATE = 3; // 0x3
     field public static final int RESULT_NOT_INITIALIZED = 2; // 0x2
@@ -4758,18 +4803,6 @@
     field public static final int SCAN_TYPE_AUTO = 1; // 0x1
     field public static final int SCAN_TYPE_BLIND = 2; // 0x2
     field public static final int SCAN_TYPE_UNDEFINED = 0; // 0x0
-    field public static final int SC_HEVC_INDEX_AUD = 2; // 0x2
-    field public static final int SC_HEVC_INDEX_SLICE_BLA_N_LP = 16; // 0x10
-    field public static final int SC_HEVC_INDEX_SLICE_BLA_W_RADL = 8; // 0x8
-    field public static final int SC_HEVC_INDEX_SLICE_CE_BLA_W_LP = 4; // 0x4
-    field public static final int SC_HEVC_INDEX_SLICE_IDR_N_LP = 64; // 0x40
-    field public static final int SC_HEVC_INDEX_SLICE_IDR_W_RADL = 32; // 0x20
-    field public static final int SC_HEVC_INDEX_SLICE_TRAIL_CRA = 128; // 0x80
-    field public static final int SC_HEVC_INDEX_SPS = 1; // 0x1
-    field public static final int SC_INDEX_B_FRAME = 4; // 0x4
-    field public static final int SC_INDEX_I_FRAME = 1; // 0x1
-    field public static final int SC_INDEX_P_FRAME = 2; // 0x2
-    field public static final int SC_INDEX_SEQUENCE = 8; // 0x8
   }
 
 }
@@ -5025,6 +5058,21 @@
     method public int getScIndexMask();
     method public int getScIndexType();
     method public int getTsIndexMask();
+    field public static final int INDEX_TYPE_NONE = 0; // 0x0
+    field public static final int INDEX_TYPE_SC = 1; // 0x1
+    field public static final int INDEX_TYPE_SC_HEVC = 2; // 0x2
+    field public static final int SC_HEVC_INDEX_AUD = 2; // 0x2
+    field public static final int SC_HEVC_INDEX_SLICE_BLA_N_LP = 16; // 0x10
+    field public static final int SC_HEVC_INDEX_SLICE_BLA_W_RADL = 8; // 0x8
+    field public static final int SC_HEVC_INDEX_SLICE_CE_BLA_W_LP = 4; // 0x4
+    field public static final int SC_HEVC_INDEX_SLICE_IDR_N_LP = 64; // 0x40
+    field public static final int SC_HEVC_INDEX_SLICE_IDR_W_RADL = 32; // 0x20
+    field public static final int SC_HEVC_INDEX_SLICE_TRAIL_CRA = 128; // 0x80
+    field public static final int SC_HEVC_INDEX_SPS = 1; // 0x1
+    field public static final int SC_INDEX_B_FRAME = 4; // 0x4
+    field public static final int SC_INDEX_I_FRAME = 1; // 0x1
+    field public static final int SC_INDEX_P_FRAME = 2; // 0x2
+    field public static final int SC_INDEX_SEQUENCE = 8; // 0x8
     field public static final int TS_INDEX_ADAPTATION_EXTENSION_FLAG = 4096; // 0x1000
     field public static final int TS_INDEX_CHANGE_TO_EVEN_SCRAMBLED = 8; // 0x8
     field public static final int TS_INDEX_CHANGE_TO_NOT_SCRAMBLED = 4; // 0x4
@@ -5143,6 +5191,11 @@
 
 package android.media.tv.tuner.frontend {
 
+  public class AnalogFrontendCapabilities extends android.media.tv.tuner.frontend.FrontendCapabilities {
+    method public int getSifStandardCapability();
+    method public int getSignalTypeCapability();
+  }
+
   public class AnalogFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
     method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public static android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder builder(@NonNull android.content.Context);
     method public int getSifStandard();
@@ -5180,8 +5233,74 @@
 
   public static class AnalogFrontendSettings.Builder extends android.media.tv.tuner.frontend.FrontendSettings.Builder<android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder> {
     method @NonNull public android.media.tv.tuner.frontend.AnalogFrontendSettings build();
-    method @NonNull public android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder setASignalType(int);
     method @NonNull public android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder setSifStandard(int);
+    method @NonNull public android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder setSignalType(int);
+  }
+
+  public class Atsc3FrontendCapabilities extends android.media.tv.tuner.frontend.FrontendCapabilities {
+    method public int getBandwidthCapability();
+    method public int getDemodOutputFormatCapability();
+    method public int getFecCapability();
+    method public int getModulationCapability();
+    method public int getPlpCodeRateCapability();
+    method public int getTimeInterleaveModeCapability();
+  }
+
+  public class Atsc3FrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
+    method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public static android.media.tv.tuner.frontend.Atsc3FrontendSettings.Builder builder(@NonNull android.content.Context);
+    method public int getBandwidth();
+    method public int getDemodOutputFormat();
+    method @NonNull public android.media.tv.tuner.frontend.Atsc3PlpSettings[] getPlpSettings();
+    method public int getType();
+    field public static final int BANDWIDTH_AUTO = 1; // 0x1
+    field public static final int BANDWIDTH_BANDWIDTH_6MHZ = 2; // 0x2
+    field public static final int BANDWIDTH_BANDWIDTH_7MHZ = 4; // 0x4
+    field public static final int BANDWIDTH_BANDWIDTH_8MHZ = 8; // 0x8
+    field public static final int BANDWIDTH_UNDEFINED = 0; // 0x0
+    field public static final int CODERATE_10_15 = 512; // 0x200
+    field public static final int CODERATE_11_15 = 1024; // 0x400
+    field public static final int CODERATE_12_15 = 2048; // 0x800
+    field public static final int CODERATE_13_15 = 4096; // 0x1000
+    field public static final int CODERATE_2_15 = 2; // 0x2
+    field public static final int CODERATE_3_15 = 4; // 0x4
+    field public static final int CODERATE_4_15 = 8; // 0x8
+    field public static final int CODERATE_5_15 = 16; // 0x10
+    field public static final int CODERATE_6_15 = 32; // 0x20
+    field public static final int CODERATE_7_15 = 64; // 0x40
+    field public static final int CODERATE_8_15 = 128; // 0x80
+    field public static final int CODERATE_9_15 = 256; // 0x100
+    field public static final int CODERATE_AUTO = 1; // 0x1
+    field public static final int CODERATE_UNDEFINED = 0; // 0x0
+    field public static final int DEMOD_OUTPUT_FORMAT_ATSC3_LINKLAYER_PACKET = 1; // 0x1
+    field public static final int DEMOD_OUTPUT_FORMAT_BASEBAND_PACKET = 2; // 0x2
+    field public static final int DEMOD_OUTPUT_FORMAT_UNDEFINED = 0; // 0x0
+    field public static final int FEC_AUTO = 1; // 0x1
+    field public static final int FEC_BCH_LDPC_16K = 2; // 0x2
+    field public static final int FEC_BCH_LDPC_64K = 4; // 0x4
+    field public static final int FEC_CRC_LDPC_16K = 8; // 0x8
+    field public static final int FEC_CRC_LDPC_64K = 16; // 0x10
+    field public static final int FEC_LDPC_16K = 32; // 0x20
+    field public static final int FEC_LDPC_64K = 64; // 0x40
+    field public static final int FEC_UNDEFINED = 0; // 0x0
+    field public static final int MODULATION_AUTO = 1; // 0x1
+    field public static final int MODULATION_MOD_1024QAM = 32; // 0x20
+    field public static final int MODULATION_MOD_16QAM = 4; // 0x4
+    field public static final int MODULATION_MOD_256QAM = 16; // 0x10
+    field public static final int MODULATION_MOD_4096QAM = 64; // 0x40
+    field public static final int MODULATION_MOD_64QAM = 8; // 0x8
+    field public static final int MODULATION_MOD_QPSK = 2; // 0x2
+    field public static final int MODULATION_UNDEFINED = 0; // 0x0
+    field public static final int TIME_INTERLEAVE_MODE_AUTO = 1; // 0x1
+    field public static final int TIME_INTERLEAVE_MODE_CTI = 2; // 0x2
+    field public static final int TIME_INTERLEAVE_MODE_HTI = 4; // 0x4
+    field public static final int TIME_INTERLEAVE_MODE_UNDEFINED = 0; // 0x0
+  }
+
+  public static class Atsc3FrontendSettings.Builder extends android.media.tv.tuner.frontend.FrontendSettings.Builder<android.media.tv.tuner.frontend.Atsc3FrontendSettings.Builder> {
+    method @NonNull public android.media.tv.tuner.frontend.Atsc3FrontendSettings build();
+    method @NonNull public android.media.tv.tuner.frontend.Atsc3FrontendSettings.Builder setBandwidth(int);
+    method @NonNull public android.media.tv.tuner.frontend.Atsc3FrontendSettings.Builder setDemodOutputFormat(byte);
+    method @NonNull public android.media.tv.tuner.frontend.Atsc3FrontendSettings.Builder setPlpSettings(@NonNull android.media.tv.tuner.frontend.Atsc3PlpSettings[]);
   }
 
   public class Atsc3PlpInfo {
@@ -5189,9 +5308,326 @@
     method public int getPlpId();
   }
 
+  public class Atsc3PlpSettings {
+    method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public static android.media.tv.tuner.frontend.Atsc3PlpSettings.Builder builder(@NonNull android.content.Context);
+    method public int getCodeRate();
+    method public int getFec();
+    method public int getInterleaveMode();
+    method public int getModulation();
+    method public int getPlpId();
+  }
+
+  public static class Atsc3PlpSettings.Builder {
+    method @NonNull public android.media.tv.tuner.frontend.Atsc3PlpSettings build();
+    method @NonNull public android.media.tv.tuner.frontend.Atsc3PlpSettings.Builder setCodeRate(int);
+    method @NonNull public android.media.tv.tuner.frontend.Atsc3PlpSettings.Builder setFec(int);
+    method @NonNull public android.media.tv.tuner.frontend.Atsc3PlpSettings.Builder setInterleaveMode(int);
+    method @NonNull public android.media.tv.tuner.frontend.Atsc3PlpSettings.Builder setModulation(int);
+    method @NonNull public android.media.tv.tuner.frontend.Atsc3PlpSettings.Builder setPlpId(int);
+  }
+
+  public class AtscFrontendCapabilities extends android.media.tv.tuner.frontend.FrontendCapabilities {
+    method public int getModulationCapability();
+  }
+
+  public class AtscFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
+    method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public static android.media.tv.tuner.frontend.AtscFrontendSettings.Builder builder(@NonNull android.content.Context);
+    method public int getModulation();
+    method public int getType();
+    field public static final int MODULATION_AUTO = 1; // 0x1
+    field public static final int MODULATION_MOD_16VSB = 8; // 0x8
+    field public static final int MODULATION_MOD_8VSB = 4; // 0x4
+    field public static final int MODULATION_UNDEFINED = 0; // 0x0
+  }
+
+  public static class AtscFrontendSettings.Builder extends android.media.tv.tuner.frontend.FrontendSettings.Builder<android.media.tv.tuner.frontend.AtscFrontendSettings.Builder> {
+    method @NonNull public android.media.tv.tuner.frontend.AtscFrontendSettings build();
+    method @NonNull public android.media.tv.tuner.frontend.AtscFrontendSettings.Builder setModulation(int);
+  }
+
+  public class DvbcFrontendCapabilities extends android.media.tv.tuner.frontend.FrontendCapabilities {
+    method public int getAnnexCapability();
+    method public int getFecCapability();
+    method public int getModulationCapability();
+  }
+
+  public class DvbcFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
+    method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public static android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder builder(@NonNull android.content.Context);
+    method public byte getAnnex();
+    method public long getFec();
+    method public int getModulation();
+    method public int getOuterFec();
+    method public int getSpectralInversion();
+    method public int getSymbolRate();
+    method public int getType();
+    field public static final int ANNEX_A = 1; // 0x1
+    field public static final int ANNEX_B = 2; // 0x2
+    field public static final int ANNEX_C = 4; // 0x4
+    field public static final int ANNEX_UNDEFINED = 0; // 0x0
+    field public static final int MODULATION_AUTO = 1; // 0x1
+    field public static final int MODULATION_MOD_128QAM = 16; // 0x10
+    field public static final int MODULATION_MOD_16QAM = 2; // 0x2
+    field public static final int MODULATION_MOD_256QAM = 32; // 0x20
+    field public static final int MODULATION_MOD_32QAM = 4; // 0x4
+    field public static final int MODULATION_MOD_64QAM = 8; // 0x8
+    field public static final int MODULATION_UNDEFINED = 0; // 0x0
+    field public static final int OUTER_FEC_OUTER_FEC_NONE = 1; // 0x1
+    field public static final int OUTER_FEC_OUTER_FEC_RS = 2; // 0x2
+    field public static final int OUTER_FEC_UNDEFINED = 0; // 0x0
+    field public static final int SPECTRAL_INVERSION_INVERTED = 2; // 0x2
+    field public static final int SPECTRAL_INVERSION_NORMAL = 1; // 0x1
+    field public static final int SPECTRAL_INVERSION_UNDEFINED = 0; // 0x0
+  }
+
+  public static class DvbcFrontendSettings.Builder extends android.media.tv.tuner.frontend.FrontendSettings.Builder<android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder> {
+    method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings build();
+    method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setAnnex(byte);
+    method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setFec(long);
+    method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setModulation(int);
+    method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setOuterFec(int);
+    method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setSpectralInversion(int);
+    method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setSymbolRate(int);
+  }
+
+  public class DvbsCodeRate {
+    method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public static android.media.tv.tuner.frontend.DvbsCodeRate.Builder builder(@NonNull android.content.Context);
+    method public int getBitsPer1000Symbol();
+    method public long getInnerFec();
+    method public boolean isLinear();
+    method public boolean isShortFrameEnabled();
+  }
+
+  public static class DvbsCodeRate.Builder {
+    method @NonNull public android.media.tv.tuner.frontend.DvbsCodeRate build();
+    method @NonNull public android.media.tv.tuner.frontend.DvbsCodeRate.Builder setBitsPer1000Symbol(int);
+    method @NonNull public android.media.tv.tuner.frontend.DvbsCodeRate.Builder setInnerFec(long);
+    method @NonNull public android.media.tv.tuner.frontend.DvbsCodeRate.Builder setLinear(boolean);
+    method @NonNull public android.media.tv.tuner.frontend.DvbsCodeRate.Builder setShortFrameEnabled(boolean);
+  }
+
+  public class DvbsFrontendCapabilities extends android.media.tv.tuner.frontend.FrontendCapabilities {
+    method public long getInnerFecCapability();
+    method public int getModulationCapability();
+    method public int getStandardCapability();
+  }
+
+  public class DvbsFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
+    method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public static android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder builder(@NonNull android.content.Context);
+    method @Nullable public android.media.tv.tuner.frontend.DvbsCodeRate getCodeRate();
+    method public int getInputStreamId();
+    method public int getModulation();
+    method public int getPilot();
+    method public int getRolloff();
+    method public int getStandard();
+    method public int getSymbolRate();
+    method public int getType();
+    method public int getVcmMode();
+    field public static final int MODULATION_AUTO = 1; // 0x1
+    field public static final int MODULATION_MOD_128APSK = 2048; // 0x800
+    field public static final int MODULATION_MOD_16APSK = 256; // 0x100
+    field public static final int MODULATION_MOD_16PSK = 16; // 0x10
+    field public static final int MODULATION_MOD_16QAM = 8; // 0x8
+    field public static final int MODULATION_MOD_256APSK = 4096; // 0x1000
+    field public static final int MODULATION_MOD_32APSK = 512; // 0x200
+    field public static final int MODULATION_MOD_32PSK = 32; // 0x20
+    field public static final int MODULATION_MOD_64APSK = 1024; // 0x400
+    field public static final int MODULATION_MOD_8APSK = 128; // 0x80
+    field public static final int MODULATION_MOD_8PSK = 4; // 0x4
+    field public static final int MODULATION_MOD_ACM = 64; // 0x40
+    field public static final int MODULATION_MOD_QPSK = 2; // 0x2
+    field public static final int MODULATION_MOD_RESERVED = 8192; // 0x2000
+    field public static final int MODULATION_UNDEFINED = 0; // 0x0
+    field public static final int PILOT_AUTO = 3; // 0x3
+    field public static final int PILOT_OFF = 2; // 0x2
+    field public static final int PILOT_ON = 1; // 0x1
+    field public static final int PILOT_UNDEFINED = 0; // 0x0
+    field public static final int ROLLOFF_0_10 = 5; // 0x5
+    field public static final int ROLLOFF_0_15 = 4; // 0x4
+    field public static final int ROLLOFF_0_20 = 3; // 0x3
+    field public static final int ROLLOFF_0_25 = 2; // 0x2
+    field public static final int ROLLOFF_0_35 = 1; // 0x1
+    field public static final int ROLLOFF_0_5 = 6; // 0x6
+    field public static final int ROLLOFF_UNDEFINED = 0; // 0x0
+    field public static final int STANDARD_AUTO = 1; // 0x1
+    field public static final int STANDARD_S = 2; // 0x2
+    field public static final int STANDARD_S2 = 4; // 0x4
+    field public static final int STANDARD_S2X = 8; // 0x8
+    field public static final int VCM_MODE_AUTO = 1; // 0x1
+    field public static final int VCM_MODE_MANUAL = 2; // 0x2
+    field public static final int VCM_MODE_UNDEFINED = 0; // 0x0
+  }
+
+  public static class DvbsFrontendSettings.Builder extends android.media.tv.tuner.frontend.FrontendSettings.Builder<android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder> {
+    method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings build();
+    method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setCodeRate(@Nullable android.media.tv.tuner.frontend.DvbsCodeRate);
+    method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setInputStreamId(int);
+    method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setModulation(int);
+    method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setPilot(int);
+    method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setRolloff(int);
+    method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setStandard(int);
+    method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setSymbolRate(int);
+    method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setVcmMode(int);
+  }
+
+  public class DvbtFrontendCapabilities extends android.media.tv.tuner.frontend.FrontendCapabilities {
+    method public int getBandwidthCapability();
+    method public int getCodeRateCapability();
+    method public int getConstellationCapability();
+    method public int getGuardIntervalCapability();
+    method public int getHierarchyCapability();
+    method public int getTransmissionModeCapability();
+    method public boolean isMisoSupported();
+    method public boolean isT2Supported();
+  }
+
+  public class DvbtFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
+    method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public static android.media.tv.tuner.frontend.DvbtFrontendSettings.Builder builder(@NonNull android.content.Context);
+    method public int getBandwidth();
+    method public int getConstellation();
+    method public int getGuardInterval();
+    method public int getHierarchy();
+    method public int getHpCodeRate();
+    method public int getLpCodeRate();
+    method public int getPlpGroupId();
+    method public int getPlpId();
+    method public int getPlpMode();
+    method public int getStandard();
+    method public int getTransmissionMode();
+    method public int getType();
+    method public boolean isHighPriority();
+    method public boolean isMiso();
+    field public static final int BANDWIDTH_10MHZ = 64; // 0x40
+    field public static final int BANDWIDTH_1_7MHZ = 32; // 0x20
+    field public static final int BANDWIDTH_5MHZ = 16; // 0x10
+    field public static final int BANDWIDTH_6MHZ = 8; // 0x8
+    field public static final int BANDWIDTH_7MHZ = 4; // 0x4
+    field public static final int BANDWIDTH_8MHZ = 2; // 0x2
+    field public static final int BANDWIDTH_AUTO = 1; // 0x1
+    field public static final int BANDWIDTH_UNDEFINED = 0; // 0x0
+    field public static final int CODERATE_1_2 = 2; // 0x2
+    field public static final int CODERATE_2_3 = 4; // 0x4
+    field public static final int CODERATE_3_4 = 8; // 0x8
+    field public static final int CODERATE_3_5 = 64; // 0x40
+    field public static final int CODERATE_4_5 = 128; // 0x80
+    field public static final int CODERATE_5_6 = 16; // 0x10
+    field public static final int CODERATE_6_7 = 256; // 0x100
+    field public static final int CODERATE_7_8 = 32; // 0x20
+    field public static final int CODERATE_8_9 = 512; // 0x200
+    field public static final int CODERATE_AUTO = 1; // 0x1
+    field public static final int CODERATE_UNDEFINED = 0; // 0x0
+    field public static final int CONSTELLATION_AUTO = 1; // 0x1
+    field public static final int CONSTELLATION_CONSTELLATION_16QAM = 4; // 0x4
+    field public static final int CONSTELLATION_CONSTELLATION_256QAM = 16; // 0x10
+    field public static final int CONSTELLATION_CONSTELLATION_64QAM = 8; // 0x8
+    field public static final int CONSTELLATION_CONSTELLATION_QPSK = 2; // 0x2
+    field public static final int CONSTELLATION_UNDEFINED = 0; // 0x0
+    field public static final int GUARD_INTERVAL_AUTO = 1; // 0x1
+    field public static final int GUARD_INTERVAL_INTERVAL_19_128 = 64; // 0x40
+    field public static final int GUARD_INTERVAL_INTERVAL_19_256 = 128; // 0x80
+    field public static final int GUARD_INTERVAL_INTERVAL_1_128 = 32; // 0x20
+    field public static final int GUARD_INTERVAL_INTERVAL_1_16 = 4; // 0x4
+    field public static final int GUARD_INTERVAL_INTERVAL_1_32 = 2; // 0x2
+    field public static final int GUARD_INTERVAL_INTERVAL_1_4 = 16; // 0x10
+    field public static final int GUARD_INTERVAL_INTERVAL_1_8 = 8; // 0x8
+    field public static final int GUARD_INTERVAL_UNDEFINED = 0; // 0x0
+    field public static final int HIERARCHY_1_INDEPTH = 64; // 0x40
+    field public static final int HIERARCHY_1_NATIVE = 4; // 0x4
+    field public static final int HIERARCHY_2_INDEPTH = 128; // 0x80
+    field public static final int HIERARCHY_2_NATIVE = 8; // 0x8
+    field public static final int HIERARCHY_4_INDEPTH = 256; // 0x100
+    field public static final int HIERARCHY_4_NATIVE = 16; // 0x10
+    field public static final int HIERARCHY_AUTO = 1; // 0x1
+    field public static final int HIERARCHY_NON_INDEPTH = 32; // 0x20
+    field public static final int HIERARCHY_NON_NATIVE = 2; // 0x2
+    field public static final int HIERARCHY_UNDEFINED = 0; // 0x0
+    field public static final int PLP_MODE_AUTO = 1; // 0x1
+    field public static final int PLP_MODE_MANUAL = 2; // 0x2
+    field public static final int PLP_MODE_UNDEFINED = 0; // 0x0
+    field public static final int STANDARD_AUTO = 1; // 0x1
+    field public static final int STANDARD_T = 2; // 0x2
+    field public static final int STANDARD_T2 = 4; // 0x4
+    field public static final int TRANSMISSION_MODE_16K = 32; // 0x20
+    field public static final int TRANSMISSION_MODE_1K = 16; // 0x10
+    field public static final int TRANSMISSION_MODE_2K = 2; // 0x2
+    field public static final int TRANSMISSION_MODE_32K = 64; // 0x40
+    field public static final int TRANSMISSION_MODE_4K = 8; // 0x8
+    field public static final int TRANSMISSION_MODE_8K = 4; // 0x4
+    field public static final int TRANSMISSION_MODE_AUTO = 1; // 0x1
+    field public static final int TRANSMISSION_MODE_UNDEFINED = 0; // 0x0
+  }
+
+  public static class DvbtFrontendSettings.Builder extends android.media.tv.tuner.frontend.FrontendSettings.Builder<android.media.tv.tuner.frontend.DvbtFrontendSettings.Builder> {
+    method @NonNull public android.media.tv.tuner.frontend.DvbtFrontendSettings build();
+    method @NonNull public android.media.tv.tuner.frontend.DvbtFrontendSettings.Builder setBandwidth(int);
+    method @NonNull public android.media.tv.tuner.frontend.DvbtFrontendSettings.Builder setConstellation(int);
+    method @NonNull public android.media.tv.tuner.frontend.DvbtFrontendSettings.Builder setGuardInterval(int);
+    method @NonNull public android.media.tv.tuner.frontend.DvbtFrontendSettings.Builder setHierarchy(int);
+    method @NonNull public android.media.tv.tuner.frontend.DvbtFrontendSettings.Builder setHighPriority(boolean);
+    method @NonNull public android.media.tv.tuner.frontend.DvbtFrontendSettings.Builder setHpCodeRate(int);
+    method @NonNull public android.media.tv.tuner.frontend.DvbtFrontendSettings.Builder setLpCodeRate(int);
+    method @NonNull public android.media.tv.tuner.frontend.DvbtFrontendSettings.Builder setMiso(boolean);
+    method @NonNull public android.media.tv.tuner.frontend.DvbtFrontendSettings.Builder setPlpGroupId(int);
+    method @NonNull public android.media.tv.tuner.frontend.DvbtFrontendSettings.Builder setPlpId(int);
+    method @NonNull public android.media.tv.tuner.frontend.DvbtFrontendSettings.Builder setPlpMode(int);
+    method @NonNull public android.media.tv.tuner.frontend.DvbtFrontendSettings.Builder setStandard(int);
+    method @NonNull public android.media.tv.tuner.frontend.DvbtFrontendSettings.Builder setTransmissionMode(int);
+  }
+
+  public abstract class FrontendCapabilities {
+    ctor public FrontendCapabilities();
+  }
+
+  public class FrontendInfo {
+    method public int getAcquireRange();
+    method public int getExclusiveGroupId();
+    method @NonNull public android.util.Range<java.lang.Integer> getFrequencyRange();
+    method @NonNull public android.media.tv.tuner.frontend.FrontendCapabilities getFrontendCapability();
+    method public int getId();
+    method @NonNull public int[] getStatusCapabilities();
+    method @NonNull public android.util.Range<java.lang.Integer> getSymbolRateRange();
+    method public int getType();
+  }
+
   public abstract class FrontendSettings {
     method public int getFrequency();
     method public abstract int getType();
+    field public static final long FEC_11_15 = 4194304L; // 0x400000L
+    field public static final long FEC_11_20 = 8388608L; // 0x800000L
+    field public static final long FEC_11_45 = 16777216L; // 0x1000000L
+    field public static final long FEC_13_18 = 33554432L; // 0x2000000L
+    field public static final long FEC_13_45 = 67108864L; // 0x4000000L
+    field public static final long FEC_14_45 = 134217728L; // 0x8000000L
+    field public static final long FEC_1_2 = 2L; // 0x2L
+    field public static final long FEC_1_3 = 4L; // 0x4L
+    field public static final long FEC_1_4 = 8L; // 0x8L
+    field public static final long FEC_1_5 = 16L; // 0x10L
+    field public static final long FEC_23_36 = 268435456L; // 0x10000000L
+    field public static final long FEC_25_36 = 536870912L; // 0x20000000L
+    field public static final long FEC_26_45 = 1073741824L; // 0x40000000L
+    field public static final long FEC_28_45 = -2147483648L; // 0xffffffff80000000L
+    field public static final long FEC_29_45 = 1L; // 0x1L
+    field public static final long FEC_2_3 = 32L; // 0x20L
+    field public static final long FEC_2_5 = 64L; // 0x40L
+    field public static final long FEC_2_9 = 128L; // 0x80L
+    field public static final long FEC_31_45 = 2L; // 0x2L
+    field public static final long FEC_32_45 = 4L; // 0x4L
+    field public static final long FEC_3_4 = 256L; // 0x100L
+    field public static final long FEC_3_5 = 512L; // 0x200L
+    field public static final long FEC_4_15 = 2048L; // 0x800L
+    field public static final long FEC_4_5 = 1024L; // 0x400L
+    field public static final long FEC_5_6 = 4096L; // 0x1000L
+    field public static final long FEC_5_9 = 8192L; // 0x2000L
+    field public static final long FEC_6_7 = 16384L; // 0x4000L
+    field public static final long FEC_77_90 = 8L; // 0x8L
+    field public static final long FEC_7_15 = 131072L; // 0x20000L
+    field public static final long FEC_7_8 = 32768L; // 0x8000L
+    field public static final long FEC_7_9 = 65536L; // 0x10000L
+    field public static final long FEC_8_15 = 524288L; // 0x80000L
+    field public static final long FEC_8_9 = 262144L; // 0x40000L
+    field public static final long FEC_9_10 = 1048576L; // 0x100000L
+    field public static final long FEC_9_20 = 2097152L; // 0x200000L
+    field public static final long FEC_AUTO = 1L; // 0x1L
+    field public static final long FEC_UNDEFINED = 0L; // 0x0L
     field public static final int TYPE_ANALOG = 1; // 0x1
     field public static final int TYPE_ATSC = 2; // 0x2
     field public static final int TYPE_ATSC3 = 3; // 0x3
@@ -5208,6 +5644,200 @@
     method @IntRange(from=1) @NonNull public T setFrequency(int);
   }
 
+  public class FrontendStatus {
+    method public int getAgc();
+    method @NonNull public android.media.tv.tuner.frontend.FrontendStatus.Atsc3PlpInfo[] getAtsc3PlpInfo();
+    method public int getBer();
+    method public long getFec();
+    method public int getFreqOffset();
+    method public int getHierarchy();
+    method @NonNull public boolean[] getLayerErrors();
+    method public int getLberCn();
+    method public int getLnbVoltage();
+    method public int getMer();
+    method public int getModulation();
+    method public int getPer();
+    method public int getPerBer();
+    method public int getPlpId();
+    method public int getSignalQuality();
+    method public int getSignalStrength();
+    method public int getSnr();
+    method public int getSpectralInversion();
+    method public int getSymbolRate();
+    method public int getVberCn();
+    method public int getXerCn();
+    method public boolean isDemodLocked();
+    method public boolean isEwbs();
+    method public boolean isLnaOn();
+    method public boolean isRfLock();
+    field public static final int FRONTEND_STATUS_TYPE_AGC = 14; // 0xe
+    field public static final int FRONTEND_STATUS_TYPE_ATSC3_PLP_INFO = 24; // 0x18
+    field public static final int FRONTEND_STATUS_TYPE_BER = 2; // 0x2
+    field public static final int FRONTEND_STATUS_TYPE_DEMOD_LOCK = 0; // 0x0
+    field public static final int FRONTEND_STATUS_TYPE_EWBS = 13; // 0xd
+    field public static final int FRONTEND_STATUS_TYPE_FEC = 8; // 0x8
+    field public static final int FRONTEND_STATUS_TYPE_FREQ_OFFSET = 21; // 0x15
+    field public static final int FRONTEND_STATUS_TYPE_HIERARCHY = 22; // 0x16
+    field public static final int FRONTEND_STATUS_TYPE_LAYER_ERROR = 16; // 0x10
+    field public static final int FRONTEND_STATUS_TYPE_LBER_CN = 18; // 0x12
+    field public static final int FRONTEND_STATUS_TYPE_LNA = 15; // 0xf
+    field public static final int FRONTEND_STATUS_TYPE_LNB_VOLTAGE = 11; // 0xb
+    field public static final int FRONTEND_STATUS_TYPE_MER = 20; // 0x14
+    field public static final int FRONTEND_STATUS_TYPE_MODULATION = 9; // 0x9
+    field public static final int FRONTEND_STATUS_TYPE_PER = 3; // 0x3
+    field public static final int FRONTEND_STATUS_TYPE_PLP_ID = 12; // 0xc
+    field public static final int FRONTEND_STATUS_TYPE_PRE_BER = 4; // 0x4
+    field public static final int FRONTEND_STATUS_TYPE_RF_LOCK = 23; // 0x17
+    field public static final int FRONTEND_STATUS_TYPE_SIGNAL_QUALITY = 5; // 0x5
+    field public static final int FRONTEND_STATUS_TYPE_SIGNAL_STRENGTH = 6; // 0x6
+    field public static final int FRONTEND_STATUS_TYPE_SNR = 1; // 0x1
+    field public static final int FRONTEND_STATUS_TYPE_SPECTRAL = 10; // 0xa
+    field public static final int FRONTEND_STATUS_TYPE_SYMBOL_RATE = 7; // 0x7
+    field public static final int FRONTEND_STATUS_TYPE_VBER_CN = 17; // 0x11
+    field public static final int FRONTEND_STATUS_TYPE_XER_CN = 19; // 0x13
+  }
+
+  public static class FrontendStatus.Atsc3PlpInfo {
+    method public int getPlpId();
+    method public int getUec();
+    method public boolean isLock();
+  }
+
+  public class Isdbs3FrontendCapabilities extends android.media.tv.tuner.frontend.FrontendCapabilities {
+    method public int getCodeRateCapability();
+    method public int getModulationCapability();
+  }
+
+  public class Isdbs3FrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
+    method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public static android.media.tv.tuner.frontend.Isdbs3FrontendSettings.Builder builder(@NonNull android.content.Context);
+    method public int getCodeRate();
+    method public int getModulation();
+    method public int getRolloff();
+    method public int getStreamId();
+    method public int getStreamIdType();
+    method public int getSymbolRate();
+    method public int getType();
+    field public static final int CODERATE_1_2 = 8; // 0x8
+    field public static final int CODERATE_1_3 = 2; // 0x2
+    field public static final int CODERATE_2_3 = 32; // 0x20
+    field public static final int CODERATE_2_5 = 4; // 0x4
+    field public static final int CODERATE_3_4 = 64; // 0x40
+    field public static final int CODERATE_3_5 = 16; // 0x10
+    field public static final int CODERATE_4_5 = 256; // 0x100
+    field public static final int CODERATE_5_6 = 512; // 0x200
+    field public static final int CODERATE_7_8 = 1024; // 0x400
+    field public static final int CODERATE_7_9 = 128; // 0x80
+    field public static final int CODERATE_9_10 = 2048; // 0x800
+    field public static final int CODERATE_AUTO = 1; // 0x1
+    field public static final int CODERATE_UNDEFINED = 0; // 0x0
+    field public static final int MODULATION_AUTO = 1; // 0x1
+    field public static final int MODULATION_MOD_16APSK = 16; // 0x10
+    field public static final int MODULATION_MOD_32APSK = 32; // 0x20
+    field public static final int MODULATION_MOD_8PSK = 8; // 0x8
+    field public static final int MODULATION_MOD_BPSK = 2; // 0x2
+    field public static final int MODULATION_MOD_QPSK = 4; // 0x4
+    field public static final int MODULATION_UNDEFINED = 0; // 0x0
+    field public static final int ROLLOFF_0_03 = 1; // 0x1
+    field public static final int ROLLOFF_UNDEFINED = 0; // 0x0
+  }
+
+  public static class Isdbs3FrontendSettings.Builder extends android.media.tv.tuner.frontend.FrontendSettings.Builder<android.media.tv.tuner.frontend.Isdbs3FrontendSettings.Builder> {
+    method @NonNull public android.media.tv.tuner.frontend.Isdbs3FrontendSettings build();
+    method @NonNull public android.media.tv.tuner.frontend.Isdbs3FrontendSettings.Builder setCodeRate(int);
+    method @NonNull public android.media.tv.tuner.frontend.Isdbs3FrontendSettings.Builder setModulation(int);
+    method @NonNull public android.media.tv.tuner.frontend.Isdbs3FrontendSettings.Builder setRolloff(int);
+    method @NonNull public android.media.tv.tuner.frontend.Isdbs3FrontendSettings.Builder setStreamId(int);
+    method @NonNull public android.media.tv.tuner.frontend.Isdbs3FrontendSettings.Builder setStreamIdType(int);
+    method @NonNull public android.media.tv.tuner.frontend.Isdbs3FrontendSettings.Builder setSymbolRate(int);
+  }
+
+  public class IsdbsFrontendCapabilities extends android.media.tv.tuner.frontend.FrontendCapabilities {
+    method public int getCodeRateCapability();
+    method public int getModulationCapability();
+  }
+
+  public class IsdbsFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
+    method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public static android.media.tv.tuner.frontend.IsdbsFrontendSettings.Builder builder(@NonNull android.content.Context);
+    method public int getCodeRate();
+    method public int getModulation();
+    method public int getRolloff();
+    method public int getStreamId();
+    method public int getStreamIdType();
+    method public int getSymbolRate();
+    method public int getType();
+    field public static final int CODERATE_1_2 = 2; // 0x2
+    field public static final int CODERATE_2_3 = 4; // 0x4
+    field public static final int CODERATE_3_4 = 8; // 0x8
+    field public static final int CODERATE_5_6 = 16; // 0x10
+    field public static final int CODERATE_7_8 = 32; // 0x20
+    field public static final int CODERATE_AUTO = 1; // 0x1
+    field public static final int CODERATE_UNDEFINED = 0; // 0x0
+    field public static final int MODULATION_AUTO = 1; // 0x1
+    field public static final int MODULATION_MOD_BPSK = 2; // 0x2
+    field public static final int MODULATION_MOD_QPSK = 4; // 0x4
+    field public static final int MODULATION_MOD_TC8PSK = 8; // 0x8
+    field public static final int MODULATION_UNDEFINED = 0; // 0x0
+    field public static final int ROLLOFF_0_35 = 1; // 0x1
+    field public static final int ROLLOFF_UNDEFINED = 0; // 0x0
+    field public static final int STREAM_ID_TYPE_ID = 0; // 0x0
+    field public static final int STREAM_ID_TYPE_RELATIVE_NUMBER = 1; // 0x1
+  }
+
+  public static class IsdbsFrontendSettings.Builder extends android.media.tv.tuner.frontend.FrontendSettings.Builder<android.media.tv.tuner.frontend.IsdbsFrontendSettings.Builder> {
+    method @NonNull public android.media.tv.tuner.frontend.IsdbsFrontendSettings build();
+    method @NonNull public android.media.tv.tuner.frontend.IsdbsFrontendSettings.Builder setCodeRate(int);
+    method @NonNull public android.media.tv.tuner.frontend.IsdbsFrontendSettings.Builder setModulation(int);
+    method @NonNull public android.media.tv.tuner.frontend.IsdbsFrontendSettings.Builder setRolloff(int);
+    method @NonNull public android.media.tv.tuner.frontend.IsdbsFrontendSettings.Builder setStreamId(int);
+    method @NonNull public android.media.tv.tuner.frontend.IsdbsFrontendSettings.Builder setStreamIdType(int);
+    method @NonNull public android.media.tv.tuner.frontend.IsdbsFrontendSettings.Builder setSymbolRate(int);
+  }
+
+  public class IsdbtFrontendCapabilities extends android.media.tv.tuner.frontend.FrontendCapabilities {
+    method public int getBandwidthCapability();
+    method public int getCodeRateCapability();
+    method public int getGuardIntervalCapability();
+    method public int getModeCapability();
+    method public int getModulationCapability();
+  }
+
+  public class IsdbtFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
+    method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public static android.media.tv.tuner.frontend.IsdbtFrontendSettings.Builder builder(@NonNull android.content.Context);
+    method public int getBandwidth();
+    method public int getCodeRate();
+    method public int getGuardInterval();
+    method public int getMode();
+    method public int getModulation();
+    method public int getServiceAreaId();
+    method public int getType();
+    field public static final int BANDWIDTH_6MHZ = 8; // 0x8
+    field public static final int BANDWIDTH_7MHZ = 4; // 0x4
+    field public static final int BANDWIDTH_8MHZ = 2; // 0x2
+    field public static final int BANDWIDTH_AUTO = 1; // 0x1
+    field public static final int BANDWIDTH_UNDEFINED = 0; // 0x0
+    field public static final int MODE_1 = 2; // 0x2
+    field public static final int MODE_2 = 4; // 0x4
+    field public static final int MODE_3 = 8; // 0x8
+    field public static final int MODE_AUTO = 1; // 0x1
+    field public static final int MODE_UNDEFINED = 0; // 0x0
+    field public static final int MODULATION_AUTO = 1; // 0x1
+    field public static final int MODULATION_MOD_16QAM = 8; // 0x8
+    field public static final int MODULATION_MOD_64QAM = 16; // 0x10
+    field public static final int MODULATION_MOD_DQPSK = 2; // 0x2
+    field public static final int MODULATION_MOD_QPSK = 4; // 0x4
+    field public static final int MODULATION_UNDEFINED = 0; // 0x0
+  }
+
+  public static class IsdbtFrontendSettings.Builder extends android.media.tv.tuner.frontend.FrontendSettings.Builder<android.media.tv.tuner.frontend.IsdbtFrontendSettings.Builder> {
+    method @NonNull public android.media.tv.tuner.frontend.IsdbtFrontendSettings build();
+    method @NonNull public android.media.tv.tuner.frontend.IsdbtFrontendSettings.Builder setBandwidth(int);
+    method @NonNull public android.media.tv.tuner.frontend.IsdbtFrontendSettings.Builder setCodeRate(int);
+    method @NonNull public android.media.tv.tuner.frontend.IsdbtFrontendSettings.Builder setGuardInterval(int);
+    method @NonNull public android.media.tv.tuner.frontend.IsdbtFrontendSettings.Builder setMode(int);
+    method @NonNull public android.media.tv.tuner.frontend.IsdbtFrontendSettings.Builder setModulation(int);
+    method @NonNull public android.media.tv.tuner.frontend.IsdbtFrontendSettings.Builder setServiceAreaId(int);
+  }
+
   public interface OnTuneEventListener {
     method public void onTuneEvent(int);
     field public static final int SIGNAL_LOCKED = 0; // 0x0
@@ -5290,6 +5920,32 @@
     field public static final int APP_RETURN_WANTED_AS_IS = 2; // 0x2
   }
 
+  public final class CaptivePortalData implements android.os.Parcelable {
+    method public int describeContents();
+    method public long getByteLimit();
+    method public long getExpiryTimeMillis();
+    method public long getRefreshTimeMillis();
+    method @Nullable public android.net.Uri getUserPortalUrl();
+    method @Nullable public android.net.Uri getVenueInfoUrl();
+    method public boolean isCaptive();
+    method public boolean isSessionExtendable();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.CaptivePortalData> CREATOR;
+  }
+
+  public static class CaptivePortalData.Builder {
+    ctor public CaptivePortalData.Builder();
+    ctor public CaptivePortalData.Builder(@Nullable android.net.CaptivePortalData);
+    method @NonNull public android.net.CaptivePortalData build();
+    method @NonNull public android.net.CaptivePortalData.Builder setBytesRemaining(long);
+    method @NonNull public android.net.CaptivePortalData.Builder setCaptive(boolean);
+    method @NonNull public android.net.CaptivePortalData.Builder setExpiryTime(long);
+    method @NonNull public android.net.CaptivePortalData.Builder setRefreshTime(long);
+    method @NonNull public android.net.CaptivePortalData.Builder setSessionExtendable(boolean);
+    method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri);
+    method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri);
+  }
+
   public class ConnectivityManager {
     method @NonNull @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createNattKeepalive(@NonNull android.net.Network, @NonNull android.os.ParcelFileDescriptor, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback);
     method @NonNull @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createSocketKeepalive(@NonNull android.net.Network, @NonNull java.net.Socket, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback);
@@ -5421,6 +6077,8 @@
     method @NonNull public java.util.List<java.lang.String> getAllInterfaceNames();
     method @NonNull public java.util.List<android.net.LinkAddress> getAllLinkAddresses();
     method @NonNull public java.util.List<android.net.RouteInfo> getAllRoutes();
+    method @Nullable public android.net.Uri getCaptivePortalApiUrl();
+    method @Nullable public android.net.CaptivePortalData getCaptivePortalData();
     method @NonNull public java.util.List<java.net.InetAddress> getPcscfServers();
     method @Nullable public String getTcpBufferSizes();
     method @NonNull public java.util.List<java.net.InetAddress> getValidatedPrivateDnsServers();
@@ -5434,9 +6092,12 @@
     method public boolean isIpv6Provisioned();
     method public boolean isProvisioned();
     method public boolean isReachable(@NonNull java.net.InetAddress);
+    method @NonNull public android.net.LinkProperties makeSensitiveFieldsParcelingCopy();
     method public boolean removeDnsServer(@NonNull java.net.InetAddress);
     method public boolean removeLinkAddress(@NonNull android.net.LinkAddress);
     method public boolean removeRoute(@NonNull android.net.RouteInfo);
+    method public void setCaptivePortalApiUrl(@Nullable android.net.Uri);
+    method public void setCaptivePortalData(@Nullable android.net.CaptivePortalData);
     method public void setPcscfServers(@NonNull java.util.Collection<java.net.InetAddress>);
     method public void setPrivateDnsServerName(@Nullable String);
     method public void setTcpBufferSizes(@Nullable String);
@@ -5521,6 +6182,7 @@
 
   public final class NetworkCapabilities implements android.os.Parcelable {
     method public boolean deduceRestrictedCapability();
+    method @Nullable public String getSSID();
     method @NonNull public int[] getTransportTypes();
     method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities);
     method @NonNull public android.net.NetworkCapabilities setSSID(@Nullable String);
@@ -5630,6 +6292,8 @@
 
   public final class RouteInfo implements android.os.Parcelable {
     ctor public RouteInfo(@Nullable android.net.IpPrefix, @Nullable java.net.InetAddress, @Nullable String, int);
+    ctor public RouteInfo(@Nullable android.net.IpPrefix, @Nullable java.net.InetAddress, @Nullable String, int, int);
+    method public int getMtu();
     method public int getType();
     field public static final int RTN_THROW = 9; // 0x9
     field public static final int RTN_UNICAST = 1; // 0x1
@@ -7742,8 +8406,11 @@
     method @Nullable @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public android.os.IncidentManager.IncidentReport getIncidentReport(android.net.Uri);
     method @NonNull @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public java.util.List<android.net.Uri> getIncidentReportList(String);
     method @RequiresPermission(android.Manifest.permission.APPROVE_INCIDENT_REPORTS) public java.util.List<android.os.IncidentManager.PendingReport> getPendingReports();
+    method public void registerSection(int, @NonNull String, @NonNull android.os.IncidentManager.DumpCallback);
+    method public void registerSection(int, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.os.IncidentManager.DumpCallback);
     method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void reportIncident(android.os.IncidentReportArgs);
     method @RequiresPermission("android.permission.REQUEST_INCIDENT_REPORT_APPROVAL") public void requestAuthorization(int, String, int, android.os.IncidentManager.AuthListener);
+    method public void unregisterSection(int);
     field public static final int FLAG_CONFIRMATION_DIALOG = 1; // 0x1
     field public static final int PRIVACY_POLICY_AUTO = 200; // 0xc8
     field public static final int PRIVACY_POLICY_EXPLICIT = 100; // 0x64
@@ -7756,6 +8423,11 @@
     method public void onReportDenied();
   }
 
+  public static class IncidentManager.DumpCallback {
+    ctor public IncidentManager.DumpCallback();
+    method public void onDumpSection(int, @NonNull java.io.OutputStream);
+  }
+
   public static class IncidentManager.IncidentReport implements java.io.Closeable android.os.Parcelable {
     ctor public IncidentManager.IncidentReport(android.os.Parcel);
     method public void close();
@@ -7811,10 +8483,14 @@
     method @RequiresPermission(allOf={android.Manifest.permission.READ_DREAM_STATE, android.Manifest.permission.WRITE_DREAM_STATE}) public void dream(long);
     method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public boolean forceSuspend();
     method @RequiresPermission(android.Manifest.permission.POWER_SAVER) public int getPowerSaveModeTrigger();
+    method @RequiresPermission(android.Manifest.permission.READ_DREAM_STATE) public boolean isAmbientDisplayAvailable();
+    method @RequiresPermission(android.Manifest.permission.READ_DREAM_STATE) public boolean isAmbientDisplaySuppressed();
+    method @RequiresPermission(android.Manifest.permission.READ_DREAM_STATE) public boolean isAmbientDisplaySuppressedForToken(@NonNull String);
     method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setAdaptivePowerSaveEnabled(boolean);
     method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setAdaptivePowerSavePolicy(@NonNull android.os.BatterySaverPolicyConfig);
     method @RequiresPermission(android.Manifest.permission.POWER_SAVER) public boolean setDynamicPowerSaveHint(boolean, int);
     method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setPowerSaveModeEnabled(boolean);
+    method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void suppressAmbientDisplay(@NonNull String, boolean);
     method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.USER_ACTIVITY}) public void userActivity(long, int, int);
     field public static final int POWER_SAVE_MODE_TRIGGER_DYNAMIC = 1; // 0x1
     field public static final int POWER_SAVE_MODE_TRIGGER_PERCENTAGE = 0; // 0x0
@@ -10154,6 +10830,19 @@
     method @NonNull public java.util.List<android.telephony.CbGeoUtils.LatLng> getVertices();
   }
 
+  public final class CdmaEriInformation implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getEriIconIndex();
+    method public int getEriIconMode();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CdmaEriInformation> CREATOR;
+    field public static final int ERI_FLASH = 2; // 0x2
+    field public static final int ERI_ICON_MODE_FLASH = 1; // 0x1
+    field public static final int ERI_ICON_MODE_NORMAL = 0; // 0x0
+    field public static final int ERI_OFF = 1; // 0x1
+    field public static final int ERI_ON = 0; // 0x0
+  }
+
   public class CellBroadcastIntents {
     method public static void sendOrderedBroadcastForBackgroundReceivers(@NonNull android.content.Context, @Nullable android.os.UserHandle, @NonNull android.content.Intent, @Nullable String, @Nullable String, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle);
   }
@@ -10772,7 +11461,7 @@
     method public void onSrvccStateChanged(int);
     method public void onVoiceActivationStateChanged(int);
     field @RequiresPermission(android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH) public static final int LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH = 512; // 0x200
-    field public static final int LISTEN_CALL_ATTRIBUTES_CHANGED = 67108864; // 0x4000000
+    field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_CALL_ATTRIBUTES_CHANGED = 67108864; // 0x4000000
     field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_CALL = 268435456; // 0x10000000
     field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 536870912; // 0x20000000
     field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_PRECISE_CALL_STATE = 2048; // 0x800
@@ -11179,6 +11868,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCarrierPrivilegeStatus(int);
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<java.lang.String> getCarrierPrivilegedPackagesForAllActiveSubscriptions();
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CarrierRestrictionRules getCarrierRestrictionRules();
+    method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CdmaEriInformation getCdmaEriInformation();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn(int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMin();
@@ -11279,6 +11969,7 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadioPower(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerState(int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerStateForSlot(int, int);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Boolean>);
     method @Deprecated public void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoiceActivationState(int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void shutdownAllRadios();
@@ -11327,12 +12018,22 @@
     field @Deprecated public static final String EXTRA_APN_TYPE = "apnType";
     field public static final String EXTRA_APN_TYPE_INT = "apnTypeInt";
     field public static final String EXTRA_DEFAULT_NETWORK_AVAILABLE = "defaultNetworkAvailable";
+    field public static final String EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE = "android.telephony.extra.DEFAULT_SUBSCRIPTION_SELECT_TYPE";
+    field public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL = 4; // 0x4
+    field public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA = 1; // 0x1
+    field public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE = 0; // 0x0
+    field public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_SMS = 3; // 0x3
+    field public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_VOICE = 2; // 0x2
     field public static final String EXTRA_ERROR_CODE = "errorCode";
     field public static final String EXTRA_PCO_ID = "pcoId";
     field public static final String EXTRA_PCO_VALUE = "pcoValue";
     field public static final String EXTRA_PHONE_IN_ECM_STATE = "android.telephony.extra.PHONE_IN_ECM_STATE";
     field public static final String EXTRA_PHONE_IN_EMERGENCY_CALL = "android.telephony.extra.PHONE_IN_EMERGENCY_CALL";
     field public static final String EXTRA_REDIRECTION_URL = "redirectionUrl";
+    field public static final String EXTRA_SIM_COMBINATION_NAMES = "android.telephony.extra.SIM_COMBINATION_NAMES";
+    field public static final String EXTRA_SIM_COMBINATION_WARNING_TYPE = "android.telephony.extra.SIM_COMBINATION_WARNING_TYPE";
+    field public static final int EXTRA_SIM_COMBINATION_WARNING_TYPE_DUAL_CDMA = 1; // 0x1
+    field public static final int EXTRA_SIM_COMBINATION_WARNING_TYPE_NONE = 0; // 0x0
     field public static final String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE";
     field public static final String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL";
     field public static final String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING = "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING";
@@ -11490,7 +12191,9 @@
     method public int getId();
     method @NonNull public String getInterfaceName();
     method public int getLinkStatus();
-    method public int getMtu();
+    method @Deprecated public int getMtu();
+    method public int getMtuV4();
+    method public int getMtuV6();
     method @NonNull public java.util.List<java.net.InetAddress> getPcscfAddresses();
     method public int getProtocolType();
     method public int getSuggestedRetryTime();
@@ -11512,7 +12215,9 @@
     method @NonNull public android.telephony.data.DataCallResponse.Builder setId(int);
     method @NonNull public android.telephony.data.DataCallResponse.Builder setInterfaceName(@NonNull String);
     method @NonNull public android.telephony.data.DataCallResponse.Builder setLinkStatus(int);
-    method @NonNull public android.telephony.data.DataCallResponse.Builder setMtu(int);
+    method @Deprecated @NonNull public android.telephony.data.DataCallResponse.Builder setMtu(int);
+    method @NonNull public android.telephony.data.DataCallResponse.Builder setMtuV4(int);
+    method @NonNull public android.telephony.data.DataCallResponse.Builder setMtuV6(int);
     method @NonNull public android.telephony.data.DataCallResponse.Builder setPcscfAddresses(@NonNull java.util.List<java.net.InetAddress>);
     method @NonNull public android.telephony.data.DataCallResponse.Builder setProtocolType(int);
     method @NonNull public android.telephony.data.DataCallResponse.Builder setSuggestedRetryTime(int);
@@ -11523,7 +12228,9 @@
     method @NonNull public String getApn();
     method public int getAuthType();
     method public int getBearerBitmask();
-    method public int getMtu();
+    method @Deprecated public int getMtu();
+    method public int getMtuV4();
+    method public int getMtuV6();
     method @Nullable public String getPassword();
     method public int getProfileId();
     method public int getProtocolType();
@@ -11548,7 +12255,9 @@
     method @NonNull public android.telephony.data.DataProfile.Builder setApn(@NonNull String);
     method @NonNull public android.telephony.data.DataProfile.Builder setAuthType(int);
     method @NonNull public android.telephony.data.DataProfile.Builder setBearerBitmask(int);
-    method @NonNull public android.telephony.data.DataProfile.Builder setMtu(int);
+    method @Deprecated @NonNull public android.telephony.data.DataProfile.Builder setMtu(int);
+    method @NonNull public android.telephony.data.DataProfile.Builder setMtuV4(int);
+    method @NonNull public android.telephony.data.DataProfile.Builder setMtuV6(int);
     method @NonNull public android.telephony.data.DataProfile.Builder setPassword(@NonNull String);
     method @NonNull public android.telephony.data.DataProfile.Builder setPersistent(boolean);
     method @NonNull public android.telephony.data.DataProfile.Builder setPreferred(boolean);
@@ -12240,7 +12949,27 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback);
+    field public static final int KEY_1X_EPDG_TIMER_SEC = 64; // 0x40
+    field public static final int KEY_1X_THRESHOLD = 59; // 0x3b
+    field public static final int KEY_AMR_BANDWIDTH_EFFICIENT_PAYLOAD_TYPE = 50; // 0x32
+    field public static final int KEY_AMR_CODEC_MODE_SET_VALUES = 0; // 0x0
+    field public static final int KEY_AMR_DEFAULT_ENCODING_MODE = 53; // 0x35
+    field public static final int KEY_AMR_OCTET_ALIGNED_PAYLOAD_TYPE = 49; // 0x31
+    field public static final int KEY_AMR_WB_BANDWIDTH_EFFICIENT_PAYLOAD_TYPE = 48; // 0x30
+    field public static final int KEY_AMR_WB_CODEC_MODE_SET_VALUES = 1; // 0x1
+    field public static final int KEY_AMR_WB_OCTET_ALIGNED_PAYLOAD_TYPE = 47; // 0x2f
+    field public static final int KEY_DTMF_NB_PAYLOAD_TYPE = 52; // 0x34
+    field public static final int KEY_DTMF_WB_PAYLOAD_TYPE = 51; // 0x33
     field public static final int KEY_EAB_PROVISIONING_STATUS = 25; // 0x19
+    field public static final int KEY_ENABLE_SILENT_REDIAL = 6; // 0x6
+    field public static final int KEY_LOCAL_BREAKOUT_PCSCF_ADDRESS = 31; // 0x1f
+    field public static final int KEY_LTE_EPDG_TIMER_SEC = 62; // 0x3e
+    field public static final int KEY_LTE_THRESHOLD_1 = 56; // 0x38
+    field public static final int KEY_LTE_THRESHOLD_2 = 57; // 0x39
+    field public static final int KEY_LTE_THRESHOLD_3 = 58; // 0x3a
+    field public static final int KEY_MINIMUM_SIP_SESSION_EXPIRATION_TIMER_SEC = 3; // 0x3
+    field public static final int KEY_MOBILE_DATA_ENABLED = 29; // 0x1d
+    field public static final int KEY_MULTIENDPOINT_ENABLED = 65; // 0x41
     field public static final int KEY_RCS_AVAILABILITY_CACHE_EXPIRATION_SEC = 19; // 0x13
     field public static final int KEY_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC = 18; // 0x12
     field public static final int KEY_RCS_CAPABILITIES_POLL_INTERVAL_SEC = 20; // 0x14
@@ -12250,16 +12979,52 @@
     field public static final int KEY_RCS_PUBLISH_SOURCE_THROTTLE_MS = 21; // 0x15
     field public static final int KEY_RCS_PUBLISH_TIMER_EXTENDED_SEC = 16; // 0x10
     field public static final int KEY_RCS_PUBLISH_TIMER_SEC = 15; // 0xf
+    field public static final int KEY_REGISTRATION_DOMAIN_NAME = 12; // 0xc
+    field public static final int KEY_REGISTRATION_RETRY_BASE_TIME_SEC = 33; // 0x21
+    field public static final int KEY_REGISTRATION_RETRY_MAX_TIME_SEC = 34; // 0x22
+    field public static final int KEY_RTP_SPEECH_END_PORT = 36; // 0x24
+    field public static final int KEY_RTP_SPEECH_START_PORT = 35; // 0x23
+    field public static final int KEY_RTT_ENABLED = 66; // 0x42
+    field public static final int KEY_SIP_ACK_RECEIPT_WAIT_TIME_MS = 43; // 0x2b
+    field public static final int KEY_SIP_ACK_RETRANSMIT_WAIT_TIME_MS = 44; // 0x2c
+    field public static final int KEY_SIP_INVITE_ACK_WAIT_TIME_MS = 38; // 0x26
+    field public static final int KEY_SIP_INVITE_CANCELLATION_TIMER_MS = 4; // 0x4
+    field public static final int KEY_SIP_INVITE_REQUEST_TRANSMIT_INTERVAL_MS = 37; // 0x25
+    field public static final int KEY_SIP_INVITE_RESPONSE_RETRANSMIT_INTERVAL_MS = 42; // 0x2a
+    field public static final int KEY_SIP_INVITE_RESPONSE_RETRANSMIT_WAIT_TIME_MS = 39; // 0x27
+    field public static final int KEY_SIP_KEEP_ALIVE_ENABLED = 32; // 0x20
+    field public static final int KEY_SIP_NON_INVITE_REQUEST_RETRANSMISSION_WAIT_TIME_MS = 45; // 0x2d
+    field public static final int KEY_SIP_NON_INVITE_REQUEST_RETRANSMIT_INTERVAL_MS = 40; // 0x28
+    field public static final int KEY_SIP_NON_INVITE_RESPONSE_RETRANSMISSION_WAIT_TIME_MS = 46; // 0x2e
+    field public static final int KEY_SIP_NON_INVITE_TRANSACTION_TIMEOUT_TIMER_MS = 41; // 0x29
+    field public static final int KEY_SIP_SESSION_TIMER_SEC = 2; // 0x2
+    field public static final int KEY_SMS_FORMAT = 13; // 0xd
+    field public static final int KEY_SMS_OVER_IP_ENABLED = 14; // 0xe
+    field public static final int KEY_SMS_PUBLIC_SERVICE_IDENTITY = 54; // 0x36
     field public static final int KEY_T1_TIMER_VALUE_MS = 7; // 0x7
+    field public static final int KEY_T2_TIMER_VALUE_MS = 8; // 0x8
+    field public static final int KEY_TF_TIMER_VALUE_MS = 9; // 0x9
+    field public static final int KEY_TRANSITION_TO_LTE_DELAY_MS = 5; // 0x5
+    field public static final int KEY_USE_GZIP_FOR_LIST_SUBSCRIPTION = 24; // 0x18
+    field public static final int KEY_VIDEO_QUALITY = 55; // 0x37
+    field public static final int KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE = 28; // 0x1c
     field public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27; // 0x1b
     field public static final int KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE = 26; // 0x1a
     field public static final int KEY_VOLTE_PROVISIONING_STATUS = 10; // 0xa
+    field public static final int KEY_VOLTE_USER_OPT_IN_STATUS = 30; // 0x1e
     field public static final int KEY_VT_PROVISIONING_STATUS = 11; // 0xb
+    field public static final int KEY_WIFI_EPDG_TIMER_SEC = 63; // 0x3f
+    field public static final int KEY_WIFI_THRESHOLD_A = 60; // 0x3c
+    field public static final int KEY_WIFI_THRESHOLD_B = 61; // 0x3d
     field public static final int PROVISIONING_RESULT_UNKNOWN = -1; // 0xffffffff
     field public static final int PROVISIONING_VALUE_DISABLED = 0; // 0x0
     field public static final int PROVISIONING_VALUE_ENABLED = 1; // 0x1
+    field public static final int SMS_FORMAT_3GPP = 1; // 0x1
+    field public static final int SMS_FORMAT_3GPP2 = 0; // 0x0
     field public static final String STRING_QUERY_RESULT_ERROR_GENERIC = "STRING_QUERY_RESULT_ERROR_GENERIC";
     field public static final String STRING_QUERY_RESULT_ERROR_NOT_READY = "STRING_QUERY_RESULT_ERROR_NOT_READY";
+    field public static final int VIDEO_QUALITY_HIGH = 1; // 0x1
+    field public static final int VIDEO_QUALITY_LOW = 0; // 0x0
   }
 
   public static class ProvisioningManager.Callback {
@@ -12895,8 +13660,8 @@
   }
 
   public interface PacProcessor {
+    method @Nullable public String findProxyForUrl(@NonNull String);
     method @NonNull public static android.webkit.PacProcessor getInstance();
-    method @Nullable public String makeProxyRequest(@NonNull String);
     method public boolean setProxyScript(@NonNull String);
   }
 
diff --git a/api/test-current.txt b/api/test-current.txt
index 7a58da4..75297e5 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1515,6 +1515,32 @@
     field public static final int APP_RETURN_WANTED_AS_IS = 2; // 0x2
   }
 
+  public final class CaptivePortalData implements android.os.Parcelable {
+    method public int describeContents();
+    method public long getByteLimit();
+    method public long getExpiryTimeMillis();
+    method public long getRefreshTimeMillis();
+    method @Nullable public android.net.Uri getUserPortalUrl();
+    method @Nullable public android.net.Uri getVenueInfoUrl();
+    method public boolean isCaptive();
+    method public boolean isSessionExtendable();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.CaptivePortalData> CREATOR;
+  }
+
+  public static class CaptivePortalData.Builder {
+    ctor public CaptivePortalData.Builder();
+    ctor public CaptivePortalData.Builder(@Nullable android.net.CaptivePortalData);
+    method @NonNull public android.net.CaptivePortalData build();
+    method @NonNull public android.net.CaptivePortalData.Builder setBytesRemaining(long);
+    method @NonNull public android.net.CaptivePortalData.Builder setCaptive(boolean);
+    method @NonNull public android.net.CaptivePortalData.Builder setExpiryTime(long);
+    method @NonNull public android.net.CaptivePortalData.Builder setRefreshTime(long);
+    method @NonNull public android.net.CaptivePortalData.Builder setSessionExtendable(boolean);
+    method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri);
+    method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri);
+  }
+
   public class ConnectivityManager {
     method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(@NonNull android.net.Network, @NonNull android.os.Bundle);
     field public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC";
@@ -1545,6 +1571,8 @@
     ctor public LinkProperties(@Nullable android.net.LinkProperties);
     method public boolean addDnsServer(@NonNull java.net.InetAddress);
     method public boolean addLinkAddress(@NonNull android.net.LinkAddress);
+    method @Nullable public android.net.Uri getCaptivePortalApiUrl();
+    method @Nullable public android.net.CaptivePortalData getCaptivePortalData();
     method @NonNull public java.util.List<java.net.InetAddress> getPcscfServers();
     method @Nullable public String getTcpBufferSizes();
     method @NonNull public java.util.List<java.net.InetAddress> getValidatedPrivateDnsServers();
@@ -1555,9 +1583,12 @@
     method public boolean isIpv6Provisioned();
     method public boolean isProvisioned();
     method public boolean isReachable(@NonNull java.net.InetAddress);
+    method @NonNull public android.net.LinkProperties makeSensitiveFieldsParcelingCopy();
     method public boolean removeDnsServer(@NonNull java.net.InetAddress);
     method public boolean removeLinkAddress(@NonNull android.net.LinkAddress);
     method public boolean removeRoute(@NonNull android.net.RouteInfo);
+    method public void setCaptivePortalApiUrl(@Nullable android.net.Uri);
+    method public void setCaptivePortalData(@Nullable android.net.CaptivePortalData);
     method public void setPcscfServers(@NonNull java.util.Collection<java.net.InetAddress>);
     method public void setPrivateDnsServerName(@Nullable String);
     method public void setTcpBufferSizes(@Nullable String);
@@ -2037,8 +2068,11 @@
     method @Nullable @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public android.os.IncidentManager.IncidentReport getIncidentReport(android.net.Uri);
     method @NonNull @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public java.util.List<android.net.Uri> getIncidentReportList(String);
     method @RequiresPermission(android.Manifest.permission.APPROVE_INCIDENT_REPORTS) public java.util.List<android.os.IncidentManager.PendingReport> getPendingReports();
+    method public void registerSection(int, @NonNull String, @NonNull android.os.IncidentManager.DumpCallback);
+    method public void registerSection(int, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.os.IncidentManager.DumpCallback);
     method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void reportIncident(android.os.IncidentReportArgs);
     method @RequiresPermission("android.permission.REQUEST_INCIDENT_REPORT_APPROVAL") public void requestAuthorization(int, String, int, android.os.IncidentManager.AuthListener);
+    method public void unregisterSection(int);
     field public static final int FLAG_CONFIRMATION_DIALOG = 1; // 0x1
     field public static final int PRIVACY_POLICY_AUTO = 200; // 0xc8
     field public static final int PRIVACY_POLICY_EXPLICIT = 100; // 0x64
@@ -2051,6 +2085,11 @@
     method public void onReportDenied();
   }
 
+  public static class IncidentManager.DumpCallback {
+    ctor public IncidentManager.DumpCallback();
+    method public void onDumpSection(int, @NonNull java.io.OutputStream);
+  }
+
   public static class IncidentManager.IncidentReport implements java.io.Closeable android.os.Parcelable {
     ctor public IncidentManager.IncidentReport(android.os.Parcel);
     method public void close();
@@ -3318,6 +3357,7 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void refreshUiccProfile();
     method @Deprecated public void setCarrierTestOverride(String, String, String, String, String, String, String);
     method public void setCarrierTestOverride(String, String, String, String, String, String, String, String, String);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Boolean>);
     method @RequiresPermission("android.permission.READ_ACTIVE_EMERGENCY_SESSION") public void updateTestOtaEmergencyNumberDbFilePath(@NonNull String);
     field public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; // 0xfffffffe
     field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1
@@ -3826,7 +3866,27 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean);
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback);
+    field public static final int KEY_1X_EPDG_TIMER_SEC = 64; // 0x40
+    field public static final int KEY_1X_THRESHOLD = 59; // 0x3b
+    field public static final int KEY_AMR_BANDWIDTH_EFFICIENT_PAYLOAD_TYPE = 50; // 0x32
+    field public static final int KEY_AMR_CODEC_MODE_SET_VALUES = 0; // 0x0
+    field public static final int KEY_AMR_DEFAULT_ENCODING_MODE = 53; // 0x35
+    field public static final int KEY_AMR_OCTET_ALIGNED_PAYLOAD_TYPE = 49; // 0x31
+    field public static final int KEY_AMR_WB_BANDWIDTH_EFFICIENT_PAYLOAD_TYPE = 48; // 0x30
+    field public static final int KEY_AMR_WB_CODEC_MODE_SET_VALUES = 1; // 0x1
+    field public static final int KEY_AMR_WB_OCTET_ALIGNED_PAYLOAD_TYPE = 47; // 0x2f
+    field public static final int KEY_DTMF_NB_PAYLOAD_TYPE = 52; // 0x34
+    field public static final int KEY_DTMF_WB_PAYLOAD_TYPE = 51; // 0x33
     field public static final int KEY_EAB_PROVISIONING_STATUS = 25; // 0x19
+    field public static final int KEY_ENABLE_SILENT_REDIAL = 6; // 0x6
+    field public static final int KEY_LOCAL_BREAKOUT_PCSCF_ADDRESS = 31; // 0x1f
+    field public static final int KEY_LTE_EPDG_TIMER_SEC = 62; // 0x3e
+    field public static final int KEY_LTE_THRESHOLD_1 = 56; // 0x38
+    field public static final int KEY_LTE_THRESHOLD_2 = 57; // 0x39
+    field public static final int KEY_LTE_THRESHOLD_3 = 58; // 0x3a
+    field public static final int KEY_MINIMUM_SIP_SESSION_EXPIRATION_TIMER_SEC = 3; // 0x3
+    field public static final int KEY_MOBILE_DATA_ENABLED = 29; // 0x1d
+    field public static final int KEY_MULTIENDPOINT_ENABLED = 65; // 0x41
     field public static final int KEY_RCS_AVAILABILITY_CACHE_EXPIRATION_SEC = 19; // 0x13
     field public static final int KEY_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC = 18; // 0x12
     field public static final int KEY_RCS_CAPABILITIES_POLL_INTERVAL_SEC = 20; // 0x14
@@ -3836,16 +3896,52 @@
     field public static final int KEY_RCS_PUBLISH_SOURCE_THROTTLE_MS = 21; // 0x15
     field public static final int KEY_RCS_PUBLISH_TIMER_EXTENDED_SEC = 16; // 0x10
     field public static final int KEY_RCS_PUBLISH_TIMER_SEC = 15; // 0xf
+    field public static final int KEY_REGISTRATION_DOMAIN_NAME = 12; // 0xc
+    field public static final int KEY_REGISTRATION_RETRY_BASE_TIME_SEC = 33; // 0x21
+    field public static final int KEY_REGISTRATION_RETRY_MAX_TIME_SEC = 34; // 0x22
+    field public static final int KEY_RTP_SPEECH_END_PORT = 36; // 0x24
+    field public static final int KEY_RTP_SPEECH_START_PORT = 35; // 0x23
+    field public static final int KEY_RTT_ENABLED = 66; // 0x42
+    field public static final int KEY_SIP_ACK_RECEIPT_WAIT_TIME_MS = 43; // 0x2b
+    field public static final int KEY_SIP_ACK_RETRANSMIT_WAIT_TIME_MS = 44; // 0x2c
+    field public static final int KEY_SIP_INVITE_ACK_WAIT_TIME_MS = 38; // 0x26
+    field public static final int KEY_SIP_INVITE_CANCELLATION_TIMER_MS = 4; // 0x4
+    field public static final int KEY_SIP_INVITE_REQUEST_TRANSMIT_INTERVAL_MS = 37; // 0x25
+    field public static final int KEY_SIP_INVITE_RESPONSE_RETRANSMIT_INTERVAL_MS = 42; // 0x2a
+    field public static final int KEY_SIP_INVITE_RESPONSE_RETRANSMIT_WAIT_TIME_MS = 39; // 0x27
+    field public static final int KEY_SIP_KEEP_ALIVE_ENABLED = 32; // 0x20
+    field public static final int KEY_SIP_NON_INVITE_REQUEST_RETRANSMISSION_WAIT_TIME_MS = 45; // 0x2d
+    field public static final int KEY_SIP_NON_INVITE_REQUEST_RETRANSMIT_INTERVAL_MS = 40; // 0x28
+    field public static final int KEY_SIP_NON_INVITE_RESPONSE_RETRANSMISSION_WAIT_TIME_MS = 46; // 0x2e
+    field public static final int KEY_SIP_NON_INVITE_TRANSACTION_TIMEOUT_TIMER_MS = 41; // 0x29
+    field public static final int KEY_SIP_SESSION_TIMER_SEC = 2; // 0x2
+    field public static final int KEY_SMS_FORMAT = 13; // 0xd
+    field public static final int KEY_SMS_OVER_IP_ENABLED = 14; // 0xe
+    field public static final int KEY_SMS_PUBLIC_SERVICE_IDENTITY = 54; // 0x36
     field public static final int KEY_T1_TIMER_VALUE_MS = 7; // 0x7
+    field public static final int KEY_T2_TIMER_VALUE_MS = 8; // 0x8
+    field public static final int KEY_TF_TIMER_VALUE_MS = 9; // 0x9
+    field public static final int KEY_TRANSITION_TO_LTE_DELAY_MS = 5; // 0x5
+    field public static final int KEY_USE_GZIP_FOR_LIST_SUBSCRIPTION = 24; // 0x18
+    field public static final int KEY_VIDEO_QUALITY = 55; // 0x37
+    field public static final int KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE = 28; // 0x1c
     field public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27; // 0x1b
     field public static final int KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE = 26; // 0x1a
     field public static final int KEY_VOLTE_PROVISIONING_STATUS = 10; // 0xa
+    field public static final int KEY_VOLTE_USER_OPT_IN_STATUS = 30; // 0x1e
     field public static final int KEY_VT_PROVISIONING_STATUS = 11; // 0xb
+    field public static final int KEY_WIFI_EPDG_TIMER_SEC = 63; // 0x3f
+    field public static final int KEY_WIFI_THRESHOLD_A = 60; // 0x3c
+    field public static final int KEY_WIFI_THRESHOLD_B = 61; // 0x3d
     field public static final int PROVISIONING_RESULT_UNKNOWN = -1; // 0xffffffff
     field public static final int PROVISIONING_VALUE_DISABLED = 0; // 0x0
     field public static final int PROVISIONING_VALUE_ENABLED = 1; // 0x1
+    field public static final int SMS_FORMAT_3GPP = 1; // 0x1
+    field public static final int SMS_FORMAT_3GPP2 = 0; // 0x0
     field public static final String STRING_QUERY_RESULT_ERROR_GENERIC = "STRING_QUERY_RESULT_ERROR_GENERIC";
     field public static final String STRING_QUERY_RESULT_ERROR_NOT_READY = "STRING_QUERY_RESULT_ERROR_NOT_READY";
+    field public static final int VIDEO_QUALITY_HIGH = 1; // 0x1
+    field public static final int VIDEO_QUALITY_LOW = 0; // 0x0
   }
 
   public static class ProvisioningManager.Callback {
diff --git a/cmds/incidentd/src/IncidentService.cpp b/cmds/incidentd/src/IncidentService.cpp
index 62312d1..6c2b855 100644
--- a/cmds/incidentd/src/IncidentService.cpp
+++ b/cmds/incidentd/src/IncidentService.cpp
@@ -350,11 +350,11 @@
 Status IncidentService::registerSection(const int id, const String16& name16,
         const sp<IIncidentDumpCallback>& callback) {
     const char* name = String8(name16).c_str();
-    ALOGI("Register section %d: %s", id, name);
+    const uid_t callingUid = IPCThreadState::self()->getCallingUid();
+    ALOGI("Uid %d registers section %d '%s'", callingUid, id, name);
     if (callback == nullptr) {
         return Status::fromExceptionCode(Status::EX_NULL_POINTER);
     }
-    const uid_t callingUid = IPCThreadState::self()->getCallingUid();
     for (int i = 0; i < mRegisteredSections.size(); i++) {
         if (mRegisteredSections.at(i)->id == id) {
             if (mRegisteredSections.at(i)->uid != callingUid) {
@@ -370,8 +370,9 @@
 }
 
 Status IncidentService::unregisterSection(const int id) {
-    ALOGI("Unregister section %d", id);
     uid_t callingUid = IPCThreadState::self()->getCallingUid();
+    ALOGI("Uid %d unregisters section %d", callingUid, id);
+
     for (auto it = mRegisteredSections.begin(); it != mRegisteredSections.end(); it++) {
         if ((*it)->id == id) {
             if ((*it)->uid != callingUid) {
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 6eafbd8..080b1af 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -73,7 +73,6 @@
         "src/external/puller_util.cpp",
         "src/external/ResourceHealthManagerPuller.cpp",
         "src/external/StatsCallbackPuller.cpp",
-        "src/external/StatsCompanionServicePuller.cpp",
         "src/external/StatsPuller.cpp",
         "src/external/StatsPullerManager.cpp",
         "src/external/SubsystemSleepStatePuller.cpp",
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 468a43f..192f3f0 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -3303,6 +3303,9 @@
     // For example, the package posting a notification, or the destination package of a share.
     optional int32 uid = 2 [(is_uid) = true];
     optional string package_name = 3;
+    // An identifier used to disambiguate which logs refer to a particular instance of some
+    // UI element. Useful when there might be multiple instances simultaneously active.
+    optional int32 instance_id = 4;
 }
 
 /**
diff --git a/cmds/statsd/src/external/StatsCompanionServicePuller.cpp b/cmds/statsd/src/external/StatsCompanionServicePuller.cpp
deleted file mode 100644
index f37d2be..0000000
--- a/cmds/statsd/src/external/StatsCompanionServicePuller.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#define DEBUG false
-#include "Log.h"
-
-#include <android/os/IStatsCompanionService.h>
-#include <binder/IPCThreadState.h>
-#include <private/android_filesystem_config.h>
-#include "../stats_log_util.h"
-#include "../statscompanion_util.h"
-#include "StatsCompanionServicePuller.h"
-
-using namespace android;
-using namespace android::base;
-using namespace android::binder;
-using namespace android::os;
-using std::make_shared;
-using std::shared_ptr;
-using std::vector;
-
-namespace android {
-namespace os {
-namespace statsd {
-
-// The reading and parsing are implemented in Java. It is not difficult to port over. But for now
-// let StatsCompanionService handle that and send the data back.
-StatsCompanionServicePuller::StatsCompanionServicePuller(int tagId) : StatsPuller(tagId) {
-}
-
-void StatsCompanionServicePuller::SetStatsCompanionService(
-        sp<IStatsCompanionService> statsCompanionService) {
-    AutoMutex _l(mStatsCompanionServiceLock);
-    sp<IStatsCompanionService> tmpForLock = mStatsCompanionService;
-    mStatsCompanionService = statsCompanionService;
-}
-
-bool StatsCompanionServicePuller::PullInternal(vector<shared_ptr<LogEvent> >* data) {
-    sp<IStatsCompanionService> statsCompanionServiceCopy = mStatsCompanionService;
-    if (statsCompanionServiceCopy != nullptr) {
-        vector<StatsLogEventWrapper> returned_value;
-        Status status = statsCompanionServiceCopy->pullData(mTagId, &returned_value);
-        if (!status.isOk()) {
-            ALOGW("StatsCompanionServicePuller::pull failed for %d", mTagId);
-            StatsdStats::getInstance().noteStatsCompanionPullFailed(mTagId);
-            if (status.exceptionCode() == Status::Exception::EX_TRANSACTION_FAILED) {
-                StatsdStats::getInstance().noteStatsCompanionPullBinderTransactionFailed(mTagId);
-            }
-            return false;
-        }
-        data->clear();
-        for (const StatsLogEventWrapper& it : returned_value) {
-            LogEvent::createLogEvents(it, *data);
-        }
-        VLOG("StatsCompanionServicePuller::pull succeeded for %d", mTagId);
-        return true;
-    } else {
-        ALOGW("statsCompanion not found!");
-        return false;
-    }
-}
-
-}  // namespace statsd
-}  // namespace os
-}  // namespace android
diff --git a/cmds/statsd/src/external/StatsCompanionServicePuller.h b/cmds/statsd/src/external/StatsCompanionServicePuller.h
deleted file mode 100644
index 2e13320..0000000
--- a/cmds/statsd/src/external/StatsCompanionServicePuller.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#pragma once
-
-#include <utils/String16.h>
-#include "StatsPuller.h"
-
-namespace android {
-namespace os {
-namespace statsd {
-
-class StatsCompanionServicePuller : public StatsPuller {
-public:
-    explicit StatsCompanionServicePuller(int tagId);
-
-    void SetStatsCompanionService(sp<IStatsCompanionService> statsCompanionService) override;
-
-private:
-    Mutex mStatsCompanionServiceLock;
-    sp<IStatsCompanionService> mStatsCompanionService = nullptr;
-    bool PullInternal(vector<std::shared_ptr<LogEvent> >* data) override;
-};
-
-}  // namespace statsd
-}  // namespace os
-}  // namespace android
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 16a65e2..8d67b5c 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -37,7 +37,6 @@
 #include "PowerStatsPuller.h"
 #include "ResourceHealthManagerPuller.h"
 #include "StatsCallbackPuller.h"
-#include "StatsCompanionServicePuller.h"
 #include "SubsystemSleepStatePuller.h"
 #include "TrainInfoPuller.h"
 #include "statslog.h"
@@ -86,16 +85,6 @@
         {{.atomTag = android::util::BATTERY_CYCLE_COUNT},
          {.puller = new ResourceHealthManagerPuller(android::util::BATTERY_CYCLE_COUNT)}},
 
-        // DebugElapsedClock.
-        {{.atomTag = android::util::DEBUG_ELAPSED_CLOCK},
-         {.additiveFields = {1, 2, 3, 4},
-          .puller = new StatsCompanionServicePuller(android::util::DEBUG_ELAPSED_CLOCK)}},
-
-        // DebugFailingElapsedClock.
-        {{.atomTag = android::util::DEBUG_FAILING_ELAPSED_CLOCK},
-         {.additiveFields = {1, 2, 3, 4},
-          .puller = new StatsCompanionServicePuller(android::util::DEBUG_FAILING_ELAPSED_CLOCK)}},
-
         // TrainInfo.
         {{.atomTag = android::util::TRAIN_INFO}, {.puller = new TrainInfoPuller()}},
 
diff --git a/core/java/android/app/admin/DevicePolicyKeyguardService.java b/core/java/android/app/admin/DevicePolicyKeyguardService.java
new file mode 100644
index 0000000..c2a76c5
--- /dev/null
+++ b/core/java/android/app/admin/DevicePolicyKeyguardService.java
@@ -0,0 +1,87 @@
+/*
+ * 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 android.app.admin;
+
+import android.annotation.Nullable;
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.SurfaceControl;
+
+/**
+ * Client interface for providing the SystemUI with secondary lockscreen information.
+ *
+ * <p>An implementation must be provided by the device admin app when
+ * {@link DevicePolicyManager#setSecondaryLockscreenEnabled} is set to true and the service must be
+ * declared in the manifest as handling the action
+ * {@link DevicePolicyManager#ACTION_BIND_SECONDARY_LOCKSCREEN_SERVICE}, otherwise the keyguard
+ * will fail to bind to the service and continue to unlock.
+ *
+ * @see DevicePolicyManager#setSecondaryLockscreenEnabled
+ */
+public class DevicePolicyKeyguardService extends Service {
+    private static final String TAG = "DevicePolicyKeyguardService";
+    private IKeyguardCallback mCallback;
+
+    private final IKeyguardClient mClient = new IKeyguardClient.Stub() {
+        @Override
+        public void onSurfaceReady(@Nullable IBinder hostInputToken, IKeyguardCallback callback) {
+            mCallback = callback;
+            SurfaceControl surfaceControl =
+                    DevicePolicyKeyguardService.this.onSurfaceReady(hostInputToken);
+
+            if (mCallback != null) {
+                try {
+                    mCallback.onSurfaceControlCreated(surfaceControl);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Failed to return created SurfaceControl", e);
+                }
+            }
+        }
+    };
+
+    @Override
+    @Nullable
+    public final IBinder onBind(@Nullable Intent intent) {
+        return mClient.asBinder();
+    }
+
+    /**
+     * Called by keyguard once the host surface for the secondary lockscreen is ready to display
+     * remote content.
+     * @return the {@link SurfaceControl} for the Surface the secondary lockscreen content is
+     *      attached to.
+     */
+    @Nullable
+    public SurfaceControl onSurfaceReady(@Nullable IBinder hostInputToken) {
+        return null;
+    }
+
+    /**
+     * Signals to keyguard that the secondary lock screen is ready to be dismissed.
+     */
+    @Nullable
+    public void dismiss() {
+        try {
+            mCallback.onDismiss();
+        } catch (RemoteException e) {
+            Log.e(TAG, "onDismiss failed", e);
+        }
+    }
+}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index a35a899..1bf6c99 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2384,6 +2384,13 @@
     public static final int MAX_PASSWORD_LENGTH = 16;
 
     /**
+     * Service Action: Service implemented by a device owner or profile owner to provide a
+     * secondary lockscreen.
+     */
+    public static final String ACTION_BIND_SECONDARY_LOCKSCREEN_SERVICE =
+            "android.app.action.BIND_SECONDARY_LOCKSCREEN_SERVICE";
+
+    /**
      * Return true if the given administrator component is currently active (enabled) in the system.
      *
      * @param admin The administrator component to check for.
@@ -4203,7 +4210,18 @@
      * device by first calling {@link #resetPassword} to set the password and then lock the device.
      * <p>
      * This method can be called on the {@link DevicePolicyManager} instance returned by
-     * {@link #getParentProfileInstance(ComponentName)} in order to lock the parent profile.
+     * {@link #getParentProfileInstance(ComponentName)} in order to lock the parent profile as
+     * well as the managed profile.
+     * <p>
+     * NOTE: In order to lock the parent profile and evict the encryption key of the managed
+     * profile, {@link #lockNow()} must be called twice: First, {@link #lockNow()} should be called
+     * on the {@link DevicePolicyManager} instance returned by
+     * {@link #getParentProfileInstance(ComponentName)}, then {@link #lockNow(int)} should be
+     * called on the {@link DevicePolicyManager} instance associated with the managed profile,
+     * with the {@link #FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY} flag.
+     * Calling the method twice in this order ensures that all users are locked and does not
+     * stop the device admin on the managed profile from issuing a second call to lock its own
+     * profile.
      *
      * @param flags May be 0 or {@link #FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY}.
      * @throws SecurityException if the calling application does not own an active administrator
@@ -4653,6 +4671,9 @@
             | DevicePolicyManager.KEYGUARD_DISABLE_BIOMETRICS;
 
     /**
+     * @deprecated This method does not actually modify the storage encryption of the device.
+     * It has never affected the encryption status of a device.
+     *
      * Called by an application that is administering the device to request that the storage system
      * be encrypted. Does nothing if the caller is on a secondary user or a managed profile.
      * <p>
@@ -4686,6 +4707,7 @@
      * @throws SecurityException if {@code admin} is not an active administrator or does not use
      *             {@link DeviceAdminInfo#USES_ENCRYPTED_STORAGE}
      */
+    @Deprecated
     public int setStorageEncryption(@NonNull ComponentName admin, boolean encrypt) {
         throwIfParentInstance("setStorageEncryption");
         if (mService != null) {
@@ -4699,6 +4721,10 @@
     }
 
     /**
+     * @deprecated This method only returns the value set by {@link #setStorageEncryption}.
+     * It does not actually reflect the storage encryption status.
+     * Use {@link #getStorageEncryptionStatus} for that.
+     *
      * Called by an application that is administering the device to
      * determine the requested setting for secure storage.
      *
@@ -4707,6 +4733,7 @@
      * administrators.
      * @return true if the admin(s) are requesting encryption, false if not.
      */
+    @Deprecated
     public boolean getStorageEncryption(@Nullable ComponentName admin) {
         throwIfParentInstance("getStorageEncryption");
         if (mService != null) {
@@ -8393,6 +8420,52 @@
     }
 
     /**
+     * Called by device owner or profile owner to set whether a secondary lockscreen needs to be
+     * shown.
+     *
+     * <p>The secondary lockscreen will by displayed after the primary keyguard security screen
+     * requirements are met. To provide the lockscreen content the DO/PO will need to provide a
+     * service handling the {@link #ACTION_BIND_SECONDARY_LOCKSCREEN_SERVICE} intent action,
+     * extending the {@link DevicePolicyKeyguardService} class.
+     *
+     * <p>Relevant interactions on the secondary lockscreen should be communicated back to the
+     * keyguard via {@link IKeyguardCallback}, such as when the screen is ready to be dismissed.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param enabled Whether or not the lockscreen needs to be shown.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
+     * @see #isSecondaryLockscreenEnabled
+     **/
+    public void setSecondaryLockscreenEnabled(@NonNull ComponentName admin, boolean enabled) {
+        throwIfParentInstance("setSecondaryLockscreenEnabled");
+        if (mService != null) {
+            try {
+                mService.setSecondaryLockscreenEnabled(admin, enabled);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
+     * Returns whether the secondary lock screen needs to be shown.
+     * @see #setSecondaryLockscreenEnabled
+     * @hide
+     */
+    @SystemApi
+    public boolean isSecondaryLockscreenEnabled(int userId) {
+        throwIfParentInstance("isSecondaryLockscreenEnabled");
+        if (mService != null) {
+            try {
+                return mService.isSecondaryLockscreenEnabled(userId);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+        return false;
+    }
+
+    /**
      * Sets which packages may enter lock task mode.
      * <p>
      * Any packages that share uid with an allowed package will also be allowed to activate lock
@@ -11337,6 +11410,10 @@
      *
      * <p>Previous calls are overridden by each subsequent call to this method.
      *
+     * <p>When previously-set cross-profile packages are missing from {@code packageNames}, the
+     * app-op for {@code INTERACT_ACROSS_PROFILES} will be reset for those packages. This will not
+     * occur for packages that are whitelisted by the OEM.
+     *
      * @param admin the {@link DeviceAdminReceiver} this request is associated with
      * @param packageNames the new cross-profile package names
      */
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index a2c0856..e7667c0 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -252,6 +252,9 @@
     String[] getAccountTypesWithManagementDisabled();
     String[] getAccountTypesWithManagementDisabledAsUser(int userId);
 
+    void setSecondaryLockscreenEnabled(in ComponentName who, boolean enabled);
+    boolean isSecondaryLockscreenEnabled(int userId);
+
     void setLockTaskPackages(in ComponentName who, in String[] packages);
     String[] getLockTaskPackages(in ComponentName who);
     boolean isLockTaskPermitted(in String pkg);
diff --git a/core/java/android/app/admin/IKeyguardCallback.aidl b/core/java/android/app/admin/IKeyguardCallback.aidl
new file mode 100644
index 0000000..81e7d4d
--- /dev/null
+++ b/core/java/android/app/admin/IKeyguardCallback.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2011 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 android.app.admin;
+
+import android.view.SurfaceControl;
+
+/**
+ * Internal IPC interface for informing the keyguard of events on the secondary lockscreen.
+ * @hide
+ */
+interface IKeyguardCallback {
+    oneway void onSurfaceControlCreated(in SurfaceControl remoteSurfaceControl);
+    oneway void onDismiss();
+}
diff --git a/core/java/android/app/admin/IKeyguardClient.aidl b/core/java/android/app/admin/IKeyguardClient.aidl
new file mode 100644
index 0000000..4bfd990
--- /dev/null
+++ b/core/java/android/app/admin/IKeyguardClient.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2011 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 android.app.admin;
+
+import android.app.admin.IKeyguardCallback;
+
+/**
+ * Internal IPC interface for a service to provide the SystemUI with secondary lockscreen
+ * information.
+ * @hide
+ */
+interface IKeyguardClient {
+    oneway void onSurfaceReady(in IBinder hostInputToken, in IKeyguardCallback keyguardCallback);
+}
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index 638e6de..7538df8 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -146,7 +146,7 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     int A2DP_SINK = 11;
 
     /**
@@ -154,7 +154,7 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     int AVRCP_CONTROLLER = 12;
 
     /**
@@ -169,6 +169,7 @@
      *
      * @hide
      */
+    @SystemApi
     int HEADSET_CLIENT = 16;
 
     /**
@@ -176,6 +177,7 @@
      *
      * @hide
      */
+    @SystemApi
     int PBAP_CLIENT = 17;
 
     /**
diff --git a/core/java/android/content/ApexContext.java b/core/java/android/content/ApexContext.java
new file mode 100644
index 0000000..fe5cedc
--- /dev/null
+++ b/core/java/android/content/ApexContext.java
@@ -0,0 +1,98 @@
+/*
+ * 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 android.content;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Environment;
+import android.os.UserHandle;
+
+import java.io.File;
+import java.util.Objects;
+
+/**
+ * Provides information about the environment for a particular APEX.
+ *
+ * @hide
+ */
+@SystemApi
+public class ApexContext {
+
+    private static final String APEX_DATA = "apexdata";
+
+    /**
+     * Returns an ApexContext instance for the APEX with the provided {@code apexModuleName}.
+     *
+     * <p>To preserve the safety and integrity of APEX modules, you must only obtain the ApexContext
+     * for your specific APEX, and you <em>must never</em> attempt to obtain an ApexContext for
+     * another APEX.  Any coordination between APEXs must be performed through well-defined
+     * interfaces; attempting to directly read or write raw files belonging to another APEX will
+     * violate the hermetic storage requirements placed upon each module.
+     */
+    @NonNull
+    public static ApexContext getApexContext(@NonNull String apexModuleName) {
+        Objects.requireNonNull(apexModuleName, "apexModuleName cannot be null");
+        //TODO(b/141148175): Check that apexModuleName is an actual APEX name
+        return new ApexContext(apexModuleName);
+    }
+
+    private final String mApexModuleName;
+
+    private ApexContext(String apexModuleName) {
+        mApexModuleName = apexModuleName;
+    }
+
+    /**
+     * Returns the data directory for the APEX in device-encrypted, non-user-specific storage.
+     *
+     * <p>This directory is automatically created by the system for installed APEXes, and its
+     * contents will be rolled back if the APEX is rolled back.
+     */
+    @NonNull
+    public File getDeviceProtectedDataDir() {
+        return Environment.buildPath(
+                Environment.getDataMiscDirectory(), APEX_DATA, mApexModuleName);
+    }
+
+    /**
+     * Returns the data directory for the APEX in device-encrypted, user-specific storage for the
+     * specified {@code user}.
+     *
+     * <p>This directory is automatically created by the system for each user and for each installed
+     * APEX, and its contents will be rolled back if the APEX is rolled back.
+     */
+    @NonNull
+    public File getDeviceProtectedDataDirForUser(@NonNull UserHandle user) {
+        return Environment.buildPath(
+                Environment.getDataMiscDeDirectory(user.getIdentifier()), APEX_DATA,
+                mApexModuleName);
+    }
+
+    /**
+     * Returns the data directory for the APEX in credential-encrypted, user-specific storage for
+     * the specified {@code user}.
+     *
+     * <p>This directory is automatically created by the system for each user and for each installed
+     * APEX, and its contents will be rolled back if the APEX is rolled back.
+     */
+    @NonNull
+    public File getCredentialProtectedDataDirForUser(@NonNull UserHandle user) {
+        return Environment.buildPath(
+                Environment.getDataMiscCeDirectory(user.getIdentifier()), APEX_DATA,
+                mApexModuleName);
+    }
+}
diff --git a/core/java/android/content/pm/CrossProfileApps.java b/core/java/android/content/pm/CrossProfileApps.java
index 5aa9c9b..de153d0 100644
--- a/core/java/android/content/pm/CrossProfileApps.java
+++ b/core/java/android/content/pm/CrossProfileApps.java
@@ -34,8 +34,10 @@
 import com.android.internal.R;
 import com.android.internal.util.UserIcons;
 
+import java.util.Collection;
 import java.util.List;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * Class for handling cross profile operations. Apps can use this class to interact with its
@@ -94,6 +96,32 @@
     }
 
     /**
+     * Starts the specified activity of the caller package in the specified profile.
+     *
+     * <p>The caller must have the {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES}
+     * permission and both the caller and target user profiles must be in the same profile group.
+     *
+     * @param intent The intent to launch. A component in the caller package must be specified.
+     * @param targetUser The {@link UserHandle} of the profile; must be one of the users returned by
+     *        {@link #getTargetUserProfiles()} if different to the calling user, otherwise a
+     *        {@link SecurityException} will be thrown.
+     */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.INTERACT_ACROSS_PROFILES,
+            android.Manifest.permission.INTERACT_ACROSS_USERS})
+    public void startActivity(@NonNull Intent intent, @NonNull UserHandle targetUser) {
+        try {
+            mService.startActivityAsUserByIntent(
+                    mContext.getIApplicationThread(),
+                    mContext.getPackageName(),
+                    intent,
+                    targetUser.getIdentifier());
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Starts the specified activity of the caller package in the specified profile. Unlike
      * {@link #startMainActivity}, this can start any activity of the caller package, not just
      * the main activity.
@@ -272,19 +300,24 @@
      * configurable by users in Settings. This configures it for the profile group of the calling
      * package.
      *
-     * <p>Before calling, check {@link #canRequestInteractAcrossProfiles()} and do not call if it is
-     * {@code false}. If presenting a user interface, do not allow the user to configure the app-op
-     * in that case.
+     * <p>Before calling, check {@link #canConfigureInteractAcrossProfiles(String)} and do not call
+     * if it is {@code false}. If presenting a user interface, do not allow the user to configure
+     * the app-op in that case.
      *
      * <p>The underlying app-op {@link android.app.AppOpsManager#OP_INTERACT_ACROSS_PROFILES} should
      * never be set directly. This method ensures that the app-op is kept in sync for the app across
      * each user in the profile group and that those apps are sent a broadcast when their ability to
      * interact across profiles changes.
      *
-     * <p>This method should be used whenever an app's ability to interact across profiles changes,
-     * as defined by the return value of {@link #canInteractAcrossProfiles()}. This includes user
-     * consent changes in Settings or during provisioning, plus changes to the admin or OEM consent
-     * whitelists that make the current app-op value invalid.
+     * <p>This method should be used directly whenever a user's action results in a change in an
+     * app's ability to interact across profiles, as defined by the return value of {@link
+     * #canInteractAcrossProfiles()}. This includes user consent changes in Settings or during
+     * provisioning.
+     *
+     * <p>If other changes could have affected the app's ability to interact across profiles, as
+     * defined by the return value of {@link #canInteractAcrossProfiles()}, such as changes to the
+     * admin or OEM consent whitelists, then {@link
+     * #resetInteractAcrossProfilesAppOpsIfInvalid(List)} should be used.
      *
      * @hide
      */
@@ -299,6 +332,58 @@
         }
     }
 
+    /**
+     * Returns whether the given package can have its ability to interact across profiles configured
+     * by the user. This means that every other condition to interact across profiles has been set.
+     *
+     * <p>This differs from {@link #canRequestInteractAcrossProfiles()} since it will not return
+     * {@code false} simply when the target profile is disabled.
+     *
+     * @hide
+     */
+    public boolean canConfigureInteractAcrossProfiles(@NonNull String packageName) {
+        try {
+            return mService.canConfigureInteractAcrossProfiles(packageName);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * For each of the packages defined in {@code previousCrossProfilePackages} but not included in
+     * {@code newCrossProfilePackages}, resets the app-op for {@link android.Manifest.permission
+     * #INTERACT_ACROSS_PROFILES} back to its default value if it can no longer be configured by
+     * users in Settings, as defined by {@link #canConfigureInteractAcrossProfiles(String)}.
+     *
+     * <p>This method should be used whenever an app's ability to interact across profiles could
+     * have changed as a result of non-user actions, such as changes to admin or OEM consent
+     * whitelists.
+     *
+     * @hide
+     */
+    @RequiresPermission(
+            allOf={android.Manifest.permission.MANAGE_APP_OPS_MODES,
+                    android.Manifest.permission.INTERACT_ACROSS_USERS})
+    public void resetInteractAcrossProfilesAppOps(
+            @NonNull Collection<String> previousCrossProfilePackages,
+            @NonNull Set<String> newCrossProfilePackages) {
+        if (previousCrossProfilePackages.isEmpty()) {
+            return;
+        }
+        final List<String> unsetCrossProfilePackages =
+                previousCrossProfilePackages.stream()
+                        .filter(packageName -> !newCrossProfilePackages.contains(packageName))
+                        .collect(Collectors.toList());
+        if (unsetCrossProfilePackages.isEmpty()) {
+            return;
+        }
+        try {
+            mService.resetInteractAcrossProfilesAppOps(unsetCrossProfilePackages);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
     private void verifyCanAccessUser(UserHandle userHandle) {
         if (!getTargetUserProfiles().contains(userHandle)) {
             throw new SecurityException("Not allowed to access " + userHandle);
diff --git a/core/java/android/content/pm/ICrossProfileApps.aidl b/core/java/android/content/pm/ICrossProfileApps.aidl
index 694b1a3..a69b988 100644
--- a/core/java/android/content/pm/ICrossProfileApps.aidl
+++ b/core/java/android/content/pm/ICrossProfileApps.aidl
@@ -29,8 +29,12 @@
 interface ICrossProfileApps {
     void startActivityAsUser(in IApplicationThread caller, in String callingPackage,
             in ComponentName component, int userId, boolean launchMainActivity);
+    void startActivityAsUserByIntent(in IApplicationThread caller, in String callingPackage,
+                        in Intent intent, int userId);
     List<UserHandle> getTargetUserProfiles(in String callingPackage);
     boolean canInteractAcrossProfiles(in String callingPackage);
     boolean canRequestInteractAcrossProfiles(in String callingPackage);
     void setInteractAcrossProfilesAppOp(in String packageName, int newMode);
+    boolean canConfigureInteractAcrossProfiles(in String packageName);
+    void resetInteractAcrossProfilesAppOps(in List<String> packageNames);
 }
\ No newline at end of file
diff --git a/core/java/android/content/pm/ModuleInfo.java b/core/java/android/content/pm/ModuleInfo.java
index d930c92..a6db662 100644
--- a/core/java/android/content/pm/ModuleInfo.java
+++ b/core/java/android/content/pm/ModuleInfo.java
@@ -37,6 +37,12 @@
     /** The package name of this module. */
     private String mPackageName;
 
+    /**
+     * The name of the APEX this module is distributed as, or null if it is not distributed via
+     * APEX.
+     */
+    @Nullable private String mApexModuleName;
+
     /** Whether or not this module is hidden from the user. */
     private boolean mHidden;
 
@@ -54,6 +60,7 @@
         mName = orig.mName;
         mPackageName = orig.mPackageName;
         mHidden = orig.mHidden;
+        mApexModuleName = orig.mApexModuleName;
     }
 
     /** @hide Sets the public name of this module. */
@@ -89,6 +96,17 @@
         return mHidden;
     }
 
+    /** @hide Sets the apex module name. */
+    public ModuleInfo setApexModuleName(@Nullable String apexModuleName) {
+        mApexModuleName = apexModuleName;
+        return this;
+    }
+
+    /** @hide Gets the apex module name. */
+    public @Nullable String getApexModuleName() {
+        return mApexModuleName;
+    }
+
     /** Returns a string representation of this object. */
     public String toString() {
         return "ModuleInfo{"
@@ -106,6 +124,7 @@
         int hashCode = 0;
         hashCode = 31 * hashCode + Objects.hashCode(mName);
         hashCode = 31 * hashCode + Objects.hashCode(mPackageName);
+        hashCode = 31 * hashCode + Objects.hashCode(mApexModuleName);
         hashCode = 31 * hashCode + Boolean.hashCode(mHidden);
         return hashCode;
     }
@@ -118,6 +137,7 @@
         final ModuleInfo other = (ModuleInfo) obj;
         return Objects.equals(mName, other.mName)
                 && Objects.equals(mPackageName, other.mPackageName)
+                && Objects.equals(mApexModuleName, other.mApexModuleName)
                 && mHidden == other.mHidden;
     }
 
@@ -126,12 +146,14 @@
         dest.writeCharSequence(mName);
         dest.writeString(mPackageName);
         dest.writeBoolean(mHidden);
+        dest.writeString(mApexModuleName);
     }
 
     private ModuleInfo(Parcel source) {
         mName = source.readCharSequence();
         mPackageName = source.readString();
         mHidden = source.readBoolean();
+        mApexModuleName = source.readString();
     }
 
     public static final @android.annotation.NonNull Parcelable.Creator<ModuleInfo> CREATOR =
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 925d70c..3c08302 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -50,6 +50,7 @@
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.graphics.Rect;
+import android.graphics.drawable.AdaptiveIconDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.wifi.WifiManager;
 import android.os.Build;
@@ -229,7 +230,7 @@
             MATCH_ALL,
     })
     @Retention(RetentionPolicy.SOURCE)
-    public @interface ModuleInfoFlags {}
+    public @interface InstalledModulesFlags {}
 
     /** @hide */
     @IntDef(flag = true, prefix = { "GET_", "MATCH_" }, value = {
@@ -581,6 +582,22 @@
     public static final int ONLY_IF_NO_MATCH_FOUND = 0x00000004;
 
     /** @hide */
+    @IntDef(flag = true, prefix = { "MODULE_" }, value = {
+            MODULE_APEX_NAME,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ModuleInfoFlags {}
+
+    /**
+     * Flag for {@link #getModuleInfo}: allow ModuleInfo to be retrieved using the apex module
+     * name, rather than the package name.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int MODULE_APEX_NAME = 0x00000001;
+
+    /** @hide */
     @IntDef(prefix = { "PERMISSION_" }, value = {
             PERMISSION_GRANTED,
             PERMISSION_DENIED
@@ -1948,6 +1965,13 @@
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_CONSUMER_IR = "android.hardware.consumerir";
 
+    /**
+     * Feature for {@link #getSystemAvailableFeatures} and
+     * {@link #hasSystemFeature}: The device supports a Context Hub.
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_CONTEXTHUB = "android.hardware.context_hub";
+
     /** {@hide} */
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_CTS = "android.software.cts";
@@ -3921,7 +3945,7 @@
      *         there are no installed modules, an empty list is returned.
      */
     @NonNull
-    public List<ModuleInfo> getInstalledModules(@ModuleInfoFlags int flags) {
+    public List<ModuleInfo> getInstalledModules(@InstalledModulesFlags int flags) {
         throw new UnsupportedOperationException(
                 "getInstalledModules not implemented in subclass");
     }
@@ -7612,4 +7636,19 @@
             "sendDeviceCustomizationReadyBroadcast not implemented in subclass");
     }
 
+    /**
+     * Returns if the provided drawable represents the default activity icon provided by the system.
+     *
+     * PackageManager provides a default icon for any package/activity if the app itself does not
+     * define one or if the system encountered any error when loading the icon.
+     *
+     * @return true if the drawable represents the default activity icon, false otherwise
+     * @see #getDefaultActivityIcon()
+     */
+    public boolean isDefaultApplicationIcon(@NonNull Drawable drawable) {
+        int resId = drawable instanceof AdaptiveIconDrawable
+                ? ((AdaptiveIconDrawable) drawable).getSourceDrawableResId() : Resources.ID_NULL;
+        return resId == com.android.internal.R.drawable.sym_def_app_icon
+                || resId == com.android.internal.R.drawable.sym_app_on_sd_unavailable_icon;
+    }
 }
diff --git a/core/java/android/debug/AdbManager.java b/core/java/android/debug/AdbManager.java
index ae3d794..0a76bed 100644
--- a/core/java/android/debug/AdbManager.java
+++ b/core/java/android/debug/AdbManager.java
@@ -16,15 +16,17 @@
 
 package android.debug;
 
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.content.Context;
+import android.os.RemoteException;
 
 /**
- * This class allows the control of ADB-related functions. Currently only ADB over USB is
- * supported, and none of the API is public.
- *
+ * This class allows the control of ADB-related functions.
  * @hide
  */
+@SystemApi
 @SystemService(Context.ADB_SERVICE)
 public class AdbManager {
     private static final String TAG = "AdbManager";
@@ -39,4 +41,33 @@
         mContext = context;
         mService = service;
     }
+
+    /**
+     * @return true if the device supports secure ADB over Wi-Fi.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_DEBUGGING)
+    public boolean isAdbWifiSupported() {
+        try {
+            return mService.isAdbWifiSupported();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * @return true if the device supports secure ADB over Wi-Fi and device pairing by
+     * QR code.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_DEBUGGING)
+    public boolean isAdbWifiQrSupported() {
+        try {
+            return mService.isAdbWifiQrSupported();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/core/java/android/debug/IAdbManager.aidl b/core/java/android/debug/IAdbManager.aidl
index 79e0794..c48fc07 100644
--- a/core/java/android/debug/IAdbManager.aidl
+++ b/core/java/android/debug/IAdbManager.aidl
@@ -41,4 +41,15 @@
      * Clear all public keys installed for secure ADB debugging.
      */
     void clearDebuggingKeys();
+
+    /**
+     * Returns true if device supports secure Adb over Wi-Fi.
+     */
+    boolean isAdbWifiSupported();
+
+    /**
+     * Returns true if device supports secure Adb over Wi-Fi and device pairing by
+     * QR code.
+     */
+    boolean isAdbWifiQrSupported();
 }
diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java
index bc7ab47..2e48ce9 100644
--- a/core/java/android/hardware/camera2/CameraCaptureSession.java
+++ b/core/java/android/hardware/camera2/CameraCaptureSession.java
@@ -19,10 +19,13 @@
 import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.hardware.camera2.CameraOfflineSession;
+import android.hardware.camera2.CameraOfflineSession.CameraOfflineSessionCallback;
 import android.hardware.camera2.params.OutputConfiguration;
 import android.os.Handler;
 import android.view.Surface;
 
+import java.util.Collection;
 import java.util.List;
 import java.util.concurrent.Executor;
 
@@ -855,6 +858,97 @@
     }
 
     /**
+     * Switch the current capture session and a given set of registered camera surfaces
+     * to offline processing mode.
+     *
+     * <p>Offline processing mode and the corresponding {@link CameraOfflineSession} differ from
+     * a regular online camera capture session in several ways. Successful offline switches will
+     * close the currently active camera capture session. Camera clients are also allowed
+     * to call {@link CameraDevice#close} while offline processing of selected capture
+     * requests is still in progress. Such side effects free device close is only possible
+     * when the offline session moves to the ready state. Once this happens, closing the camera
+     * device will not affect the pending offline requests and they must complete as normal.</p>
+     *
+     * <p>Offline processing mode switches may need several hundred milliseconds to complete
+     * as the underlying camera implementation must abort all currently active repeating requests
+     * as well as all other pending requests not specified by the client. Additionally the switch
+     * will be blocked until all requests that continue processing within the offline session
+     * acquire their initial input frame from camera sensor. The call to {@link #switchToOffline}
+     * itself is not blocking and will only trigger the offline switch sequence. Clients will
+     * be notified via {@link CameraOfflineSessionCallback#onReady} once the entire sequence is
+     * complete.</p>
+     *
+     * <p>Please note that after a successful call to this method the currently active capture
+     * session will no longer be valid and clients will begin receiving capture
+     * callbacks with a corresponding {@link CameraOfflineSession} passed as a session
+     * argument.</p>
+     *
+     * @param offlineSurfaces Client-specified collection of input/output camera registered surfaces
+     *                        that need to be switched to offline mode along with their pending
+     *                        capture requests. Do note that not all camera registered
+     *                        surfaces can be switched to offline mode. Offline processing
+     *                        support for individual surfaces can be queried using
+     *                        {@link #supportsOfflineProcessing}. Additionally offline mode
+     *                        switches are not available for shared surfaces
+     *                        {@link OutputConfiguration#enableSurfaceSharing} and surfaces
+     *                        as part of a surface group.
+     *
+     * @param executor The executor which will be used for invoking the offline callback listener.
+     *
+     * @param listener The callback object to notify for offline session events.
+     *
+     * @return camera offline session which in case of successful offline switch will move in ready
+     *         state after clients receive {@link CameraOfflineSessionCallback#onReady}. In case the
+     *         offline switch was not successful clients will receive respective
+     *         {@link CameraOfflineSessionCallback#onSwitchFailed} notification.
+     *
+     * @throws IllegalArgumentException if an attempt was made to pass a {@link Surface} that was
+     *                                  not registered with this capture session or a shared
+     *                                  surface {@link OutputConfiguration#enableSurfaceSharing} or
+     *                                  surface as part of a surface group. The current capture
+     *                                  session will remain valid and active in case of this
+     *                                  exception.
+     *
+     * @throws CameraAccessException if the camera device is no longer connected or has
+     *                               encountered a fatal error.
+     *
+     * @see CameraOfflineSession
+     * @see CameraOfflineSessionCallback
+     * @see #supportsOfflineProcessing
+     */
+    @Nullable
+    public CameraOfflineSession switchToOffline(@NonNull Collection<Surface> offlineSurfaces,
+            @NonNull Executor executor, @NonNull CameraOfflineSessionCallback listener)
+            throws CameraAccessException {
+        throw new UnsupportedOperationException("Subclasses must override this method");
+    }
+
+    /**
+     * <p>Query whether a given Surface is able to support offline mode. </p>
+     *
+     * <p>Surfaces that support offline mode can be passed as arguments to {@link #switchToOffline}.
+     * </p>
+     *
+     * @param surface An input/output surface that was used to create this session or the result of
+     *                {@link #getInputSurface}.
+     *
+     * @return {@code true} if the surface can support offline mode and can be passed as argument to
+     *         {@link #switchToOffline}. {@code false} otherwise.
+     *
+     * @throws IllegalArgumentException if an attempt was made to pass a {@link Surface} that was
+     *                                  not registered with this capture session.
+     * @throws UnsupportedOperationException if an attempt was made to call this method using
+     *                                       unsupported camera capture session like
+     *                                       {@link CameraConstrainedHighSpeedCaptureSession} or
+     *                                       {@link CameraOfflineSession}.
+     *
+     * @see #switchToOffline
+     */
+    public boolean supportsOfflineProcessing(@NonNull Surface surface) {
+        throw new UnsupportedOperationException("Subclasses must override this method");
+    }
+
+    /**
      * Close this capture session asynchronously.
      *
      * <p>Closing a session frees up the target output Surfaces of the session for reuse with either
diff --git a/core/java/android/hardware/camera2/CameraOfflineSession.java b/core/java/android/hardware/camera2/CameraOfflineSession.java
new file mode 100644
index 0000000..312559c
--- /dev/null
+++ b/core/java/android/hardware/camera2/CameraOfflineSession.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2019 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 android.hardware.camera2;
+
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CameraDevice;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * A camera capture session that was switched to offline mode via successful call to
+ * {@link CameraCaptureSession#switchToOffline}.
+ *
+ * <p>Offline capture sessions allow clients to select a set of camera registered surfaces that
+ * support offline mode.  After a successful offline mode switch all non-repeating pending requests
+ * on those surfaces will continue to be processed by the camera stack even if clients close the
+ * corresponding camera device.<p>
+ *
+ * <p>Offline capture session instances will replace the previously active capture session arguments
+ * in all capture callbacks after {@link CameraCaptureSession#switchToOffline} completes.</p>
+ *
+ * <p>Processing of pending offline capture requests will begin only after the offline session
+ * moves to ready state which will be indicated by the {@link CameraOfflineSessionCallback#onReady}
+ * callback.</p>
+ *
+ * <p>In contrast to a regular {@link CameraCaptureSession} an offline capture session will
+ * not accept any further capture requests. Besides {@link CameraOfflineSession#close} all
+ * remaining methods will throw {@link UnsupportedOperationException} and are not supported.</p>
+ *
+ * @see CameraCaptureSession#supportsOfflineProcessing
+ */
+public abstract class CameraOfflineSession extends CameraCaptureSession {
+    public static abstract class CameraOfflineSessionCallback {
+        /**
+         * This method indicates that the offline switch call
+         * {@link CameraCaptureSession#switchToOffline} was successful.
+         *
+         * <p>This callback will be invoked once the offline session moves to the ready state.</p>
+         *
+         * <p>Calls to {@link CameraDevice#close} will not have impact on the processing of offline
+         * requests once the offline session moves in ready state.</p>
+         *
+         * @param session the currently ready offline session
+         *
+         */
+        public abstract void onReady(@NonNull CameraOfflineSession session);
+
+        /**
+         * This method indicates that the offline switch call
+         * {@link CameraCaptureSession#switchToOffline} was not able to complete successfully.
+         *
+         * <p>The offline switch can fail either due to internal camera error during the switch
+         * sequence or because the camera implementation was not able to find any pending capture
+         * requests that can be migrated to offline mode.</p>
+         *
+         * <p>Calling {@link CameraOfflineSession#close} is not necessary and clients will not
+         * receive any further offline session notifications.</p>
+         *
+         * @param session the offline session that failed to switch to ready state
+         */
+        public abstract void onSwitchFailed(@NonNull CameraOfflineSession session);
+
+        /**
+         * This method indicates that all pending offline requests were processed.
+         *
+         * <p>This callback will be invoked once the offline session finishes processing
+         * all of its pending offline capture requests.</p>
+         *
+         * @param session the currently ready offline session
+         *
+         */
+        public abstract void onIdle(@NonNull CameraOfflineSession session);
+
+        /**
+         * This status code indicates unexpected and fatal internal camera error.
+         *
+         * <p>Pending offline requests will be discarded and the respective registered
+         * capture callbacks may not get triggered.</p>
+         *
+         * @see #onError
+         */
+        public static final int STATUS_INTERNAL_ERROR = 0;
+
+        /** @hide */
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef(prefix = {"STATUS_"}, value = {STATUS_INTERNAL_ERROR})
+        public @interface StatusCode {};
+
+        /**
+         * This method is called when the offline session encounters an unexpected error.
+         *
+         * <p>This notification will only be invoked for sessions that reached the ready state.
+         * Clients will need to call {@link CameraOfflineSession#close} to close and release all
+         * resources. {@link #onClosed} will not be triggered automatically in error scenarios.</p>
+         *
+         * @param session the current offline session
+         * @param status error status
+         *
+         */
+        public abstract void onError(@NonNull CameraOfflineSession session, @StatusCode int status);
+
+        /**
+         * This method is called when the offline session is closed.
+         *
+         * <p>An offline session will be closed after a call to
+         * {@link CameraOfflineSession#close}.</p>
+         *
+         * <p>In case of failure to switch to offline mode, only {@link #onSwitchFailed} will be
+         * called and {@link #onClosed} will not be.</p>
+         *
+         * <p>In case there was no previous {@link #onIdle} notification any in-progress
+         * offline capture requests within the offline session will be discarded
+         * and further result callbacks will not be triggered.</p>
+         *
+         * @param session the session returned by {@link CameraCaptureSession#switchToOffline}
+         *
+         */
+        public abstract void onClosed(@NonNull CameraOfflineSession session);
+    }
+
+    /**
+     * Close this offline capture session.
+     *
+     * <p>Abort all pending offline requests and close the connection to the offline camera session
+     * as quickly as possible.</p>
+     *
+     * <p>This method can be called only after clients receive
+     * {@link CameraOfflineSessionCallback#onReady}.</p>
+     *
+     * <p>Immediately after this call, besides the final
+     * {@link CameraOfflineSessionCallback#onClosed} notification, no further callbacks from the
+     * offline session will be triggered and all remaining offline capture requests will be
+     * discarded.</p>
+     *
+     * <p>Closing a session is idempotent; closing more than once has no effect.</p>
+     *
+     * @throws IllegalStateException if the offline sesion is not ready.
+     */
+    @Override
+    public abstract void close();
+}
diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionCore.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionCore.java
index 116f0f1..44408c2 100644
--- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionCore.java
+++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionCore.java
@@ -61,4 +61,14 @@
      */
     boolean isAborting();
 
+    /**
+     * Close the capture session without draining the pending requests.
+     *
+     * <p>This is usually used when switching to offline session mode. Depending
+     * on the client input, some of the pending requests will be flushed and some
+     * will remain for further processing. In either case, the regular drain logic
+     * needs to be skipped.</p>
+     *
+     */
+    void closeWithoutDraining();
 }
diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
index a4640c1..b6f4bd3 100644
--- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
@@ -18,6 +18,8 @@
 import android.hardware.camera2.CameraAccessException;
 import android.hardware.camera2.CameraCaptureSession;
 import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraOfflineSession;
+import android.hardware.camera2.CameraOfflineSession.CameraOfflineSessionCallback;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.ICameraDeviceUser;
 import android.hardware.camera2.params.OutputConfiguration;
@@ -29,6 +31,7 @@
 import android.view.Surface;
 
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.List;
 import java.util.concurrent.Executor;
 
@@ -106,7 +109,7 @@
          * Use the same handler as the device's StateCallback for all the internal coming events
          *
          * This ensures total ordering between CameraDevice.StateCallback and
-         * CameraDeviceImpl.CaptureCallback events.
+         * CaptureCallback events.
          */
         mSequenceDrainer = new TaskDrainer<>(mDeviceExecutor, new SequenceDrainListener(),
                 /*name*/"seq");
@@ -136,23 +139,35 @@
 
     @Override
     public void prepare(Surface surface) throws CameraAccessException {
-        mDeviceImpl.prepare(surface);
+        synchronized (mDeviceImpl.mInterfaceLock) {
+            checkNotClosed();
+            mDeviceImpl.prepare(surface);
+        }
     }
 
     @Override
     public void prepare(int maxCount, Surface surface) throws CameraAccessException {
-        mDeviceImpl.prepare(maxCount, surface);
+        synchronized (mDeviceImpl.mInterfaceLock) {
+            checkNotClosed();
+            mDeviceImpl.prepare(maxCount, surface);
+        }
     }
 
     @Override
     public void tearDown(Surface surface) throws CameraAccessException {
-        mDeviceImpl.tearDown(surface);
+        synchronized (mDeviceImpl.mInterfaceLock) {
+            checkNotClosed();
+            mDeviceImpl.tearDown(surface);
+        }
     }
 
     @Override
     public void finalizeOutputConfigurations(
             List<OutputConfiguration> outputConfigs) throws CameraAccessException {
-        mDeviceImpl.finalizeOutputConfigs(outputConfigs);
+        synchronized (mDeviceImpl.mInterfaceLock) {
+            checkNotClosed();
+            mDeviceImpl.finalizeOutputConfigs(outputConfigs);
+        }
     }
 
     @Override
@@ -446,6 +461,24 @@
     }
 
     @Override
+    public CameraOfflineSession switchToOffline(Collection<Surface> offlineOutputs,
+            Executor executor, CameraOfflineSessionCallback listener) throws CameraAccessException {
+        synchronized (mDeviceImpl.mInterfaceLock) {
+            checkNotClosed();
+        }
+        return mDeviceImpl.switchToOffline(offlineOutputs, executor, listener);
+    }
+
+
+    @Override
+    public boolean supportsOfflineProcessing(Surface surface) {
+        synchronized (mDeviceImpl.mInterfaceLock) {
+            checkNotClosed();
+        }
+        return mDeviceImpl.supportsOfflineProcessing(surface);
+    }
+
+    @Override
     public boolean isReprocessable() {
         return mInput != null;
     }
@@ -501,6 +534,25 @@
     }
 
     @Override
+    public void closeWithoutDraining() {
+        synchronized (mDeviceImpl.mInterfaceLock) {
+            if (mClosed) {
+                if (DEBUG) Log.v(TAG, mIdString + "close - reentering");
+                return;
+            }
+
+            if (DEBUG) Log.v(TAG, mIdString + "close - first time");
+
+            mClosed = true;
+            mStateCallback.onClosed(this);
+        }
+
+        if (mInput != null) {
+            mInput.release();
+        }
+    }
+
+    @Override
     public void close() {
         synchronized (mDeviceImpl.mInterfaceLock) {
             if (mClosed) {
@@ -571,13 +623,13 @@
     }
 
     /**
-     * Forward callbacks from
-     * CameraDeviceImpl.CaptureCallback to the CameraCaptureSession.CaptureCallback.
+     * Forward callbacks that usually originate from
+     * CameraDeviceImpl.CameraDeviceCallbacks to the CameraCaptureSession.CaptureCallback.
      *
      * <p>When a capture sequence finishes, update the pending checked sequences set.</p>
      */
     @SuppressWarnings("deprecation")
-    private CameraDeviceImpl.CaptureCallback createCaptureCallbackProxy(
+    private android.hardware.camera2.impl.CaptureCallback createCaptureCallbackProxy(
             Handler handler, CaptureCallback callback) {
         final Executor executor = (callback != null) ? CameraDeviceImpl.checkAndWrapHandler(
                 handler) : null;
@@ -585,9 +637,9 @@
         return createCaptureCallbackProxyWithExecutor(executor, callback);
     }
 
-    private CameraDeviceImpl.CaptureCallback createCaptureCallbackProxyWithExecutor(
+    private android.hardware.camera2.impl.CaptureCallback createCaptureCallbackProxyWithExecutor(
             Executor executor, CaptureCallback callback) {
-        return new CameraDeviceImpl.CaptureCallback() {
+        return new android.hardware.camera2.impl.CaptureCallback(executor, callback) {
             @Override
             public void onCaptureStarted(CameraDevice camera,
                     CaptureRequest request, long timestamp, long frameNumber) {
diff --git a/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java
index eb33137..0a42981 100644
--- a/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java
@@ -20,6 +20,8 @@
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraConstrainedHighSpeedCaptureSession;
 import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraOfflineSession;
+import android.hardware.camera2.CameraOfflineSession.CameraOfflineSessionCallback;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.params.OutputConfiguration;
 import android.hardware.camera2.params.StreamConfigurationMap;
@@ -283,6 +285,25 @@
     }
 
     @Override
+    public CameraOfflineSession switchToOffline(Collection<Surface> offlineOutputs,
+            Executor executor, CameraOfflineSessionCallback listener) throws CameraAccessException {
+        throw new UnsupportedOperationException("Constrained high speed session doesn't support"
+                + " this method");
+    }
+
+    @Override
+    public boolean supportsOfflineProcessing(Surface surface) {
+        throw new UnsupportedOperationException("Constrained high speed session doesn't support" +
+                " offline mode");
+    }
+
+    @Override
+    public void closeWithoutDraining() {
+        throw new UnsupportedOperationException("Constrained high speed session doesn't support"
+                + " this method");
+    }
+
+    @Override
     public void close() {
         mSessionImpl.close();
     }
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index 67e7a4c..a385771 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -23,6 +23,7 @@
 import android.hardware.camera2.CameraAccessException;
 import android.hardware.camera2.CameraCaptureSession;
 import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraOfflineSession;
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CaptureFailure;
 import android.hardware.camera2.CaptureRequest;
@@ -52,18 +53,17 @@
 
 import java.util.AbstractMap.SimpleEntry;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
-import java.util.TreeMap;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.Executor;
-
+import java.util.concurrent.Executors;
+import java.util.concurrent.ExecutorService;
 
 /**
  * HAL2.1+ implementation of CameraDevice. Use CameraManager#open to instantiate
@@ -103,6 +103,9 @@
     private final SparseArray<OutputConfiguration> mConfiguredOutputs =
             new SparseArray<>();
 
+    // Cache all stream IDs capable of supporting offline mode.
+    private final HashSet<Integer> mOfflineSupport = new HashSet<>();
+
     private final String mCameraId;
     private final CameraCharacteristics mCharacteristics;
     private final int mTotalPartialCount;
@@ -127,6 +130,9 @@
 
     private final int mAppTargetSdkVersion;
 
+    private ExecutorService mOfflineSwitchService;
+    private CameraOfflineSessionImpl mOfflineSessionImpl;
+
     // Runnables for all state transitions, except error, which needs the
     // error code argument
 
@@ -470,10 +476,19 @@
                     }
                 }
 
+                int offlineStreamIds[];
                 if (sessionParams != null) {
-                    mRemoteDevice.endConfigure(operatingMode, sessionParams.getNativeCopy());
+                    offlineStreamIds = mRemoteDevice.endConfigure(operatingMode,
+                            sessionParams.getNativeCopy());
                 } else {
-                    mRemoteDevice.endConfigure(operatingMode, null);
+                    offlineStreamIds = mRemoteDevice.endConfigure(operatingMode, null);
+                }
+
+                mOfflineSupport.clear();
+                if ((offlineStreamIds != null) && (offlineStreamIds.length > 0)) {
+                    for (int offlineStreamId : offlineStreamIds) {
+                        mOfflineSupport.add(offlineStreamId);
+                    }
                 }
 
                 success = true;
@@ -866,22 +881,29 @@
         }
     }
 
-    public void switchToOffline(ICameraDeviceCallbacks cbs, Surface[] offlineOutputs)
+    public CameraOfflineSession switchToOffline(
+            @NonNull Collection<Surface> offlineOutputs, @NonNull Executor executor,
+            @NonNull CameraOfflineSession.CameraOfflineSessionCallback listener)
             throws CameraAccessException {
-        if ((offlineOutputs == null) || (offlineOutputs.length == 0)) {
-            throw new IllegalArgumentException("Invalid offline outputs!");
-        }
-        if (cbs == null) {
-            throw new IllegalArgumentException("Invalid device callbacks!");
+        if (offlineOutputs.isEmpty()) {
+            throw new IllegalArgumentException("Invalid offline surfaces!");
         }
 
-        ICameraOfflineSession offlineSession = null;
+        HashSet<Integer> offlineStreamIds = new HashSet<Integer>();
+        SparseArray<OutputConfiguration> offlineConfiguredOutputs =
+                new SparseArray<OutputConfiguration>();
+
         synchronized(mInterfaceLock) {
-            int streamId = -1;
+            if (mOfflineSessionImpl != null) {
+                throw new IllegalStateException("Switch to offline mode already in progress");
+            }
+
             for (Surface surface : offlineOutputs) {
+                int streamId = -1;
                 for (int i = 0; i < mConfiguredOutputs.size(); i++) {
                     if (surface == mConfiguredOutputs.valueAt(i).getSurface()) {
                         streamId = mConfiguredOutputs.keyAt(i);
+                        offlineConfiguredOutputs.append(streamId, mConfiguredOutputs.valueAt(i));
                         break;
                     }
                 }
@@ -889,12 +911,67 @@
                     throw new IllegalArgumentException("Offline surface is not part of this" +
                             " session");
                 }
+
+                if (!mOfflineSupport.contains(streamId)) {
+                    throw new IllegalArgumentException("Surface: "  + surface + " does not " +
+                            " support offline mode");
+                }
+
+                offlineStreamIds.add(streamId);
             }
 
-            offlineSession = mRemoteDevice.switchToOffline(cbs,
-                    offlineOutputs);
-            // TODO: Initialize CameraOfflineSession wrapper, clear 'mConfiguredOutputs',
-            // and update request tracking
+            mOfflineSessionImpl = new CameraOfflineSessionImpl(mCameraId,
+                    mCharacteristics, executor, listener, offlineConfiguredOutputs,
+                    mConfiguredInput, mFrameNumberTracker, mCaptureCallbackMap,
+                    mRequestLastFrameNumbersList);
+
+            mOfflineSwitchService = Executors.newSingleThreadExecutor();
+            mConfiguredOutputs.clear();
+            mConfiguredInput = new SimpleEntry<Integer, InputConfiguration>(REQUEST_ID_NONE, null);
+
+            mCurrentSession.closeWithoutDraining();
+            mCurrentSession = null;
+        }
+
+        mOfflineSwitchService.execute(new Runnable() {
+            @Override
+            public void run() {
+                // We cannot hold 'mInterfaceLock' during the remote IPC in 'switchToOffline'.
+                // The call will block until all non-offline requests are completed and/or flushed.
+                // The results/errors need to be handled by 'CameraDeviceCallbacks' which also sync
+                // on 'mInterfaceLock'.
+                try {
+                    ICameraOfflineSession remoteOfflineSession = mRemoteDevice.switchToOffline(
+                            mOfflineSessionImpl.getCallbacks(),
+                            Arrays.stream(offlineStreamIds.toArray(
+                                    new Integer[offlineStreamIds.size()])).mapToInt(
+                                            Integer::intValue).toArray());
+                    mOfflineSessionImpl.setRemoteSession(remoteOfflineSession);
+                } catch (CameraAccessException e) {
+                    mOfflineSessionImpl.notifyFailedSwitch();
+                }
+            }
+        });
+
+        return mOfflineSessionImpl;
+    }
+
+    public boolean supportsOfflineProcessing(Surface surface) {
+        if (surface == null) throw new IllegalArgumentException("Surface is null");
+
+        synchronized(mInterfaceLock) {
+            int streamId = -1;
+            for (int i = 0; i < mConfiguredOutputs.size(); i++) {
+                if (surface == mConfiguredOutputs.valueAt(i).getSurface()) {
+                    streamId = mConfiguredOutputs.keyAt(i);
+                    break;
+                }
+            }
+            if (streamId == -1) {
+                throw new IllegalArgumentException("Surface is not part of this session");
+            }
+
+            return mOfflineSupport.contains(streamId);
         }
     }
 
@@ -985,7 +1062,7 @@
             final int[] repeatingRequestTypes) {
         // lastFrameNumber being equal to NO_FRAMES_CAPTURED means that the request
         // was never sent to HAL. Should trigger onCaptureSequenceAborted immediately.
-        if (lastFrameNumber == CaptureCallback.NO_FRAMES_CAPTURED) {
+        if (lastFrameNumber == CameraCaptureSession.CaptureCallback.NO_FRAMES_CAPTURED) {
             final CaptureCallbackHolder holder;
             int index = mCaptureCallbackMap.indexOfKey(requestId);
             holder = (index >= 0) ? mCaptureCallbackMap.valueAt(index) : null;
@@ -1225,6 +1302,11 @@
                 return;
             }
 
+            if (mOfflineSwitchService != null) {
+                mOfflineSwitchService.shutdownNow();
+                mOfflineSwitchService = null;
+            }
+
             if (mRemoteDevice != null) {
                 mRemoteDevice.disconnect();
                 mRemoteDevice.unlinkToDeath(this, /*flags*/0);
@@ -1286,91 +1368,6 @@
     }
 
     /**
-     * <p>A callback for tracking the progress of a {@link CaptureRequest}
-     * submitted to the camera device.</p>
-     *
-     * An interface instead of an abstract class because this is internal and
-     * we want to make sure we always implement all its callbacks until we reach
-     * the public layer.
-     */
-    public interface CaptureCallback {
-
-        /**
-         * This constant is used to indicate that no images were captured for
-         * the request.
-         *
-         * @hide
-         */
-        public static final int NO_FRAMES_CAPTURED = -1;
-
-        /**
-         * This method is called when the camera device has started capturing
-         * the output image for the request, at the beginning of image exposure.
-         *
-         * @see android.media.MediaActionSound
-         */
-        public void onCaptureStarted(CameraDevice camera,
-                CaptureRequest request, long timestamp, long frameNumber);
-
-        /**
-         * This method is called when some results from an image capture are
-         * available.
-         *
-         * @hide
-         */
-        public void onCapturePartial(CameraDevice camera,
-                CaptureRequest request, CaptureResult result);
-
-        /**
-         * This method is called when an image capture makes partial forward progress; some
-         * (but not all) results from an image capture are available.
-         *
-         */
-        public void onCaptureProgressed(CameraDevice camera,
-                CaptureRequest request, CaptureResult partialResult);
-
-        /**
-         * This method is called when an image capture has fully completed and all the
-         * result metadata is available.
-         */
-        public void onCaptureCompleted(CameraDevice camera,
-                CaptureRequest request, TotalCaptureResult result);
-
-        /**
-         * This method is called instead of {@link #onCaptureCompleted} when the
-         * camera device failed to produce a {@link CaptureResult} for the
-         * request.
-         */
-        public void onCaptureFailed(CameraDevice camera,
-                CaptureRequest request, CaptureFailure failure);
-
-        /**
-         * This method is called independently of the others in CaptureCallback,
-         * when a capture sequence finishes and all {@link CaptureResult}
-         * or {@link CaptureFailure} for it have been returned via this callback.
-         */
-        public void onCaptureSequenceCompleted(CameraDevice camera,
-                int sequenceId, long frameNumber);
-
-        /**
-         * This method is called independently of the others in CaptureCallback,
-         * when a capture sequence aborts before any {@link CaptureResult}
-         * or {@link CaptureFailure} for it have been returned via this callback.
-         */
-        public void onCaptureSequenceAborted(CameraDevice camera,
-                int sequenceId);
-
-        /**
-         * This method is called independently of the others in CaptureCallback, if an output buffer
-         * is dropped for a particular capture request.
-         *
-         * Loss of metadata is communicated via onCaptureFailed, independently of any buffer loss.
-         */
-        public void onCaptureBufferLost(CameraDevice camera,
-                CaptureRequest request, Surface target, long frameNumber);
-    }
-
-    /**
      * A callback for notifications about the state of a camera device, adding in the callbacks that
      * were part of the earlier KK API design, but now only used internally.
      */
@@ -1426,478 +1423,6 @@
         }
     }
 
-    static class CaptureCallbackHolder {
-
-        private final boolean mRepeating;
-        private final CaptureCallback mCallback;
-        private final List<CaptureRequest> mRequestList;
-        private final Executor mExecutor;
-        private final int mSessionId;
-        /**
-         * <p>Determine if the callback holder is for a constrained high speed request list that
-         * expects batched capture results. Capture results will be batched if the request list
-         * is interleaved with preview and video requests. Capture results won't be batched if the
-         * request list only contains preview requests, or if the request doesn't belong to a
-         * constrained high speed list.
-         */
-        private final boolean mHasBatchedOutputs;
-
-        CaptureCallbackHolder(CaptureCallback callback, List<CaptureRequest> requestList,
-                Executor executor, boolean repeating, int sessionId) {
-            if (callback == null || executor == null) {
-                throw new UnsupportedOperationException(
-                    "Must have a valid handler and a valid callback");
-            }
-            mRepeating = repeating;
-            mExecutor = executor;
-            mRequestList = new ArrayList<CaptureRequest>(requestList);
-            mCallback = callback;
-            mSessionId = sessionId;
-
-            // Check whether this callback holder is for batched outputs.
-            // The logic here should match createHighSpeedRequestList.
-            boolean hasBatchedOutputs = true;
-            for (int i = 0; i < requestList.size(); i++) {
-                CaptureRequest request = requestList.get(i);
-                if (!request.isPartOfCRequestList()) {
-                    hasBatchedOutputs = false;
-                    break;
-                }
-                if (i == 0) {
-                    Collection<Surface> targets = request.getTargets();
-                    if (targets.size() != 2) {
-                        hasBatchedOutputs = false;
-                        break;
-                    }
-                }
-            }
-            mHasBatchedOutputs = hasBatchedOutputs;
-        }
-
-        public boolean isRepeating() {
-            return mRepeating;
-        }
-
-        public CaptureCallback getCallback() {
-            return mCallback;
-        }
-
-        public CaptureRequest getRequest(int subsequenceId) {
-            if (subsequenceId >= mRequestList.size()) {
-                throw new IllegalArgumentException(
-                        String.format(
-                                "Requested subsequenceId %d is larger than request list size %d.",
-                                subsequenceId, mRequestList.size()));
-            } else {
-                if (subsequenceId < 0) {
-                    throw new IllegalArgumentException(String.format(
-                            "Requested subsequenceId %d is negative", subsequenceId));
-                } else {
-                    return mRequestList.get(subsequenceId);
-                }
-            }
-        }
-
-        public CaptureRequest getRequest() {
-            return getRequest(0);
-        }
-
-        public Executor getExecutor() {
-            return mExecutor;
-        }
-
-        public int getSessionId() {
-            return mSessionId;
-        }
-
-        public int getRequestCount() {
-            return mRequestList.size();
-        }
-
-        public boolean hasBatchedOutputs() {
-            return mHasBatchedOutputs;
-        }
-    }
-
-    /**
-     * This class holds a capture ID and its expected last regular, zslStill, and reprocess
-     * frame number.
-     */
-    static class RequestLastFrameNumbersHolder {
-        // request ID
-        private final int mRequestId;
-        // The last regular frame number for this request ID. It's
-        // CaptureCallback.NO_FRAMES_CAPTURED if the request ID has no regular request.
-        private final long mLastRegularFrameNumber;
-        // The last reprocess frame number for this request ID. It's
-        // CaptureCallback.NO_FRAMES_CAPTURED if the request ID has no reprocess request.
-        private final long mLastReprocessFrameNumber;
-        // The last ZSL still capture frame number for this request ID. It's
-        // CaptureCallback.NO_FRAMES_CAPTURED if the request ID has no zsl request.
-        private final long mLastZslStillFrameNumber;
-
-        /**
-         * Create a request-last-frame-numbers holder with a list of requests, request ID, and
-         * the last frame number returned by camera service.
-         */
-        public RequestLastFrameNumbersHolder(List<CaptureRequest> requestList, SubmitInfo requestInfo) {
-            long lastRegularFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
-            long lastReprocessFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
-            long lastZslStillFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
-            long frameNumber = requestInfo.getLastFrameNumber();
-
-            if (requestInfo.getLastFrameNumber() < requestList.size() - 1) {
-                throw new IllegalArgumentException(
-                        "lastFrameNumber: " + requestInfo.getLastFrameNumber() +
-                        " should be at least " + (requestList.size() - 1) + " for the number of " +
-                        " requests in the list: " + requestList.size());
-            }
-
-            // find the last regular, zslStill, and reprocess frame number
-            for (int i = requestList.size() - 1; i >= 0; i--) {
-                CaptureRequest request = requestList.get(i);
-                int requestType = request.getRequestType();
-                if (requestType == CaptureRequest.REQUEST_TYPE_REPROCESS
-                        && lastReprocessFrameNumber == CaptureCallback.NO_FRAMES_CAPTURED) {
-                    lastReprocessFrameNumber = frameNumber;
-                } else if (requestType == CaptureRequest.REQUEST_TYPE_ZSL_STILL
-                        && lastZslStillFrameNumber == CaptureCallback.NO_FRAMES_CAPTURED) {
-                    lastZslStillFrameNumber = frameNumber;
-                } else if (requestType == CaptureRequest.REQUEST_TYPE_REGULAR
-                        && lastRegularFrameNumber == CaptureCallback.NO_FRAMES_CAPTURED) {
-                    lastRegularFrameNumber = frameNumber;
-                }
-
-                if (lastReprocessFrameNumber != CaptureCallback.NO_FRAMES_CAPTURED
-                        && lastZslStillFrameNumber != CaptureCallback.NO_FRAMES_CAPTURED
-                        && lastRegularFrameNumber != CaptureCallback.NO_FRAMES_CAPTURED) {
-                    break;
-                }
-
-                frameNumber--;
-            }
-
-            mLastRegularFrameNumber = lastRegularFrameNumber;
-            mLastReprocessFrameNumber = lastReprocessFrameNumber;
-            mLastZslStillFrameNumber = lastZslStillFrameNumber;
-            mRequestId = requestInfo.getRequestId();
-        }
-
-        /**
-         * Create a request-last-frame-numbers holder with a request ID and last regular/ZslStill
-         * frame number.
-         */
-        RequestLastFrameNumbersHolder(int requestId, long lastFrameNumber,
-                int[] repeatingRequestTypes) {
-            long lastRegularFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
-            long lastZslStillFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
-
-            if (repeatingRequestTypes == null) {
-                throw new IllegalArgumentException(
-                        "repeatingRequest list must not be null");
-            }
-            if (lastFrameNumber < repeatingRequestTypes.length - 1) {
-                throw new IllegalArgumentException(
-                        "lastFrameNumber: " + lastFrameNumber + " should be at least "
-                        + (repeatingRequestTypes.length - 1)
-                        + " for the number of requests in the list: "
-                        + repeatingRequestTypes.length);
-            }
-
-            long frameNumber = lastFrameNumber;
-            for (int i = repeatingRequestTypes.length - 1; i >= 0; i--) {
-                if (repeatingRequestTypes[i] == CaptureRequest.REQUEST_TYPE_ZSL_STILL
-                        && lastZslStillFrameNumber == CaptureCallback.NO_FRAMES_CAPTURED) {
-                    lastZslStillFrameNumber = frameNumber;
-                } else if (repeatingRequestTypes[i] == CaptureRequest.REQUEST_TYPE_REGULAR
-                        && lastRegularFrameNumber == CaptureCallback.NO_FRAMES_CAPTURED) {
-                    lastRegularFrameNumber = frameNumber;
-                }
-
-                if (lastZslStillFrameNumber != CaptureCallback.NO_FRAMES_CAPTURED
-                        && lastRegularFrameNumber != CaptureCallback.NO_FRAMES_CAPTURED) {
-                    break;
-                }
-
-                frameNumber--;
-            }
-
-            mLastRegularFrameNumber = lastRegularFrameNumber;
-            mLastZslStillFrameNumber = lastZslStillFrameNumber;
-            mLastReprocessFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
-            mRequestId = requestId;
-        }
-
-        /**
-         * Return the last regular frame number. Return CaptureCallback.NO_FRAMES_CAPTURED if
-         * it contains no regular request.
-         */
-        public long getLastRegularFrameNumber() {
-            return mLastRegularFrameNumber;
-        }
-
-        /**
-         * Return the last reprocess frame number. Return CaptureCallback.NO_FRAMES_CAPTURED if
-         * it contains no reprocess request.
-         */
-        public long getLastReprocessFrameNumber() {
-            return mLastReprocessFrameNumber;
-        }
-
-        /**
-         * Return the last ZslStill frame number. Return CaptureCallback.NO_FRAMES_CAPTURED if
-         * it contains no Zsl request.
-         */
-        public long getLastZslStillFrameNumber() {
-            return mLastZslStillFrameNumber;
-        }
-
-        /**
-         * Return the last frame number overall.
-         */
-        public long getLastFrameNumber() {
-            return Math.max(mLastZslStillFrameNumber,
-                    Math.max(mLastRegularFrameNumber, mLastReprocessFrameNumber));
-        }
-
-        /**
-         * Return the request ID.
-         */
-        public int getRequestId() {
-            return mRequestId;
-        }
-    }
-
-    /**
-     * This class tracks the last frame number for submitted requests.
-     */
-    public class FrameNumberTracker {
-
-        /** the completed frame number for each type of capture results */
-        private long[] mCompletedFrameNumber = new long[CaptureRequest.REQUEST_TYPE_COUNT];
-
-        /** the skipped frame numbers that don't belong to each type of capture results */
-        private final LinkedList<Long>[] mSkippedOtherFrameNumbers =
-                new LinkedList[CaptureRequest.REQUEST_TYPE_COUNT];
-
-        /** the skipped frame numbers that belong to each type of capture results */
-        private final LinkedList<Long>[] mSkippedFrameNumbers =
-                new LinkedList[CaptureRequest.REQUEST_TYPE_COUNT];
-
-        /** frame number -> request type */
-        private final TreeMap<Long, Integer> mFutureErrorMap = new TreeMap<Long, Integer>();
-        /** Map frame numbers to list of partial results */
-        private final HashMap<Long, List<CaptureResult>> mPartialResults = new HashMap<>();
-
-        public FrameNumberTracker() {
-            for (int i = 0; i < CaptureRequest.REQUEST_TYPE_COUNT; i++) {
-                mCompletedFrameNumber[i] = CaptureCallback.NO_FRAMES_CAPTURED;
-                mSkippedOtherFrameNumbers[i] = new LinkedList<Long>();
-                mSkippedFrameNumbers[i] = new LinkedList<Long>();
-            }
-        }
-
-        private void update() {
-            Iterator iter = mFutureErrorMap.entrySet().iterator();
-            while (iter.hasNext()) {
-                TreeMap.Entry pair = (TreeMap.Entry)iter.next();
-                Long errorFrameNumber = (Long)pair.getKey();
-                int requestType = (int) pair.getValue();
-                Boolean removeError = false;
-                if (errorFrameNumber == mCompletedFrameNumber[requestType] + 1) {
-                    mCompletedFrameNumber[requestType] = errorFrameNumber;
-                    removeError = true;
-                } else {
-                    if (!mSkippedFrameNumbers[requestType].isEmpty()) {
-                        if (errorFrameNumber == mSkippedFrameNumbers[requestType].element()) {
-                            mCompletedFrameNumber[requestType] = errorFrameNumber;
-                            mSkippedFrameNumbers[requestType].remove();
-                            removeError = true;
-                        }
-                    } else {
-                        for (int i = 1; i < CaptureRequest.REQUEST_TYPE_COUNT; i++) {
-                            int otherType = (requestType + i) % CaptureRequest.REQUEST_TYPE_COUNT;
-                            if (!mSkippedOtherFrameNumbers[otherType].isEmpty() && errorFrameNumber
-                                    == mSkippedOtherFrameNumbers[otherType].element()) {
-                                mCompletedFrameNumber[requestType] = errorFrameNumber;
-                                mSkippedOtherFrameNumbers[otherType].remove();
-                                removeError = true;
-                                break;
-                            }
-                        }
-                    }
-                }
-                if (removeError) {
-                    iter.remove();
-                }
-            }
-        }
-
-        /**
-         * This function is called every time when a result or an error is received.
-         * @param frameNumber the frame number corresponding to the result or error
-         * @param isError true if it is an error, false if it is not an error
-         * @param requestType the type of capture request: Reprocess, ZslStill, or Regular.
-         */
-        public void updateTracker(long frameNumber, boolean isError, int requestType) {
-            if (isError) {
-                mFutureErrorMap.put(frameNumber, requestType);
-            } else {
-                try {
-                    updateCompletedFrameNumber(frameNumber, requestType);
-                } catch (IllegalArgumentException e) {
-                    Log.e(TAG, e.getMessage());
-                }
-            }
-            update();
-        }
-
-        /**
-         * This function is called every time a result has been completed.
-         *
-         * <p>It keeps a track of all the partial results already created for a particular
-         * frame number.</p>
-         *
-         * @param frameNumber the frame number corresponding to the result
-         * @param result the total or partial result
-         * @param partial {@true} if the result is partial, {@code false} if total
-         * @param requestType the type of capture request: Reprocess, ZslStill, or Regular.
-         */
-        public void updateTracker(long frameNumber, CaptureResult result, boolean partial,
-                int requestType) {
-            if (!partial) {
-                // Update the total result's frame status as being successful
-                updateTracker(frameNumber, /*isError*/false, requestType);
-                // Don't keep a list of total results, we don't need to track them
-                return;
-            }
-
-            if (result == null) {
-                // Do not record blank results; this also means there will be no total result
-                // so it doesn't matter that the partials were not recorded
-                return;
-            }
-
-            // Partial results must be aggregated in-order for that frame number
-            List<CaptureResult> partials = mPartialResults.get(frameNumber);
-            if (partials == null) {
-                partials = new ArrayList<>();
-                mPartialResults.put(frameNumber, partials);
-            }
-
-            partials.add(result);
-        }
-
-        /**
-         * Attempt to pop off all of the partial results seen so far for the {@code frameNumber}.
-         *
-         * <p>Once popped-off, the partial results are forgotten (unless {@code updateTracker}
-         * is called again with new partials for that frame number).</p>
-         *
-         * @param frameNumber the frame number corresponding to the result
-         * @return a list of partial results for that frame with at least 1 element,
-         *         or {@code null} if there were no partials recorded for that frame
-         */
-        public List<CaptureResult> popPartialResults(long frameNumber) {
-            return mPartialResults.remove(frameNumber);
-        }
-
-        public long getCompletedFrameNumber() {
-            return mCompletedFrameNumber[CaptureRequest.REQUEST_TYPE_REGULAR];
-        }
-
-        public long getCompletedReprocessFrameNumber() {
-            return mCompletedFrameNumber[CaptureRequest.REQUEST_TYPE_REPROCESS];
-        }
-
-        public long getCompletedZslStillFrameNumber() {
-            return mCompletedFrameNumber[CaptureRequest.REQUEST_TYPE_ZSL_STILL];
-        }
-
-        /**
-         * Update the completed frame number for results of 3 categories
-         * (Regular/Reprocess/ZslStill).
-         *
-         * It validates that all previous frames of the same category have arrived.
-         *
-         * If there is a gap since previous frame number of the same category, assume the frames in
-         * the gap are other categories and store them in the skipped frame number queue to check
-         * against when frames of those categories arrive.
-         */
-        private void updateCompletedFrameNumber(long frameNumber,
-                int requestType) throws IllegalArgumentException {
-            if (frameNumber <= mCompletedFrameNumber[requestType]) {
-                throw new IllegalArgumentException("frame number " + frameNumber + " is a repeat");
-            }
-
-            // Assume there are only 3 different types of capture requests.
-            int otherType1 = (requestType + 1) % CaptureRequest.REQUEST_TYPE_COUNT;
-            int otherType2 = (requestType + 2) % CaptureRequest.REQUEST_TYPE_COUNT;
-            long maxOtherFrameNumberSeen =
-                    Math.max(mCompletedFrameNumber[otherType1], mCompletedFrameNumber[otherType2]);
-            if (frameNumber < maxOtherFrameNumberSeen) {
-                // if frame number is smaller than completed frame numbers of other categories,
-                // it must be:
-                // - the head of mSkippedFrameNumbers for this category, or
-                // - in one of other mSkippedOtherFrameNumbers
-                if (!mSkippedFrameNumbers[requestType].isEmpty()) {
-                    // frame number must be head of current type of mSkippedFrameNumbers if
-                    // mSkippedFrameNumbers isn't empty.
-                    if (frameNumber < mSkippedFrameNumbers[requestType].element()) {
-                        throw new IllegalArgumentException("frame number " + frameNumber
-                                + " is a repeat");
-                    } else if (frameNumber > mSkippedFrameNumbers[requestType].element()) {
-                        throw new IllegalArgumentException("frame number " + frameNumber
-                                + " comes out of order. Expecting "
-                                + mSkippedFrameNumbers[requestType].element());
-                    }
-                    // frame number matches the head of the skipped frame number queue.
-                    mSkippedFrameNumbers[requestType].remove();
-                } else {
-                    // frame number must be in one of the other mSkippedOtherFrameNumbers.
-                    int index1 = mSkippedOtherFrameNumbers[otherType1].indexOf(frameNumber);
-                    int index2 = mSkippedOtherFrameNumbers[otherType2].indexOf(frameNumber);
-                    boolean inSkippedOther1 = index1 != -1;
-                    boolean inSkippedOther2 = index2 != -1;
-                    if (!(inSkippedOther1 ^ inSkippedOther2)) {
-                        throw new IllegalArgumentException("frame number " + frameNumber
-                                + " is a repeat or invalid");
-                    }
-
-                    // We know the category of frame numbers in skippedOtherFrameNumbers leading up
-                    // to the current frame number. Move them into the correct skippedFrameNumbers.
-                    LinkedList<Long> srcList, dstList;
-                    int index;
-                    if (inSkippedOther1) {
-                        srcList = mSkippedOtherFrameNumbers[otherType1];
-                        dstList = mSkippedFrameNumbers[otherType2];
-                        index = index1;
-                    } else {
-                        srcList = mSkippedOtherFrameNumbers[otherType2];
-                        dstList = mSkippedFrameNumbers[otherType1];
-                        index = index2;
-                    }
-                    for (int i = 0; i < index; i++) {
-                        dstList.add(srcList.removeFirst());
-                    }
-
-                    // Remove current frame number from skippedOtherFrameNumbers
-                    srcList.remove();
-                }
-            } else {
-                // there is a gap of unseen frame numbers which should belong to the other
-                // 2 categories. Put all the skipped frame numbers in the queue.
-                for (long i =
-                        Math.max(maxOtherFrameNumberSeen, mCompletedFrameNumber[requestType]) + 1;
-                        i < frameNumber; i++) {
-                    mSkippedOtherFrameNumbers[requestType].add(i);
-                }
-            }
-
-            mCompletedFrameNumber[requestType] = frameNumber;
-        }
-    }
-
     private void checkAndFireSequenceComplete() {
         long completedFrameNumber = mFrameNumberTracker.getCompletedFrameNumber();
         long completedReprocessFrameNumber = mFrameNumberTracker.getCompletedReprocessFrameNumber();
@@ -1979,6 +1504,201 @@
         }
     }
 
+    public void onDeviceError(final int errorCode, CaptureResultExtras resultExtras) {
+        if (DEBUG) {
+            Log.d(TAG, String.format(
+                    "Device error received, code %d, frame number %d, request ID %d, subseq ID %d",
+                    errorCode, resultExtras.getFrameNumber(), resultExtras.getRequestId(),
+                    resultExtras.getSubsequenceId()));
+        }
+
+        synchronized(mInterfaceLock) {
+            if (mRemoteDevice == null) {
+                return; // Camera already closed
+            }
+
+            // Redirect device callback to the offline session in case we are in the middle
+            // of an offline switch
+            if (mOfflineSessionImpl != null) {
+                mOfflineSessionImpl.getCallbacks().onDeviceError(errorCode, resultExtras);
+                return;
+            }
+
+            switch (errorCode) {
+                case CameraDeviceCallbacks.ERROR_CAMERA_DISCONNECTED:
+                    final long ident = Binder.clearCallingIdentity();
+                    try {
+                        mDeviceExecutor.execute(mCallOnDisconnected);
+                    } finally {
+                        Binder.restoreCallingIdentity(ident);
+                    }
+                    break;
+                case CameraDeviceCallbacks.ERROR_CAMERA_REQUEST:
+                case CameraDeviceCallbacks.ERROR_CAMERA_RESULT:
+                case CameraDeviceCallbacks.ERROR_CAMERA_BUFFER:
+                    onCaptureErrorLocked(errorCode, resultExtras);
+                    break;
+                case CameraDeviceCallbacks.ERROR_CAMERA_DEVICE:
+                    scheduleNotifyError(StateCallback.ERROR_CAMERA_DEVICE);
+                    break;
+                case CameraDeviceCallbacks.ERROR_CAMERA_DISABLED:
+                    scheduleNotifyError(StateCallback.ERROR_CAMERA_DISABLED);
+                    break;
+                default:
+                    Log.e(TAG, "Unknown error from camera device: " + errorCode);
+                    scheduleNotifyError(StateCallback.ERROR_CAMERA_SERVICE);
+            }
+        }
+    }
+
+    private void scheduleNotifyError(int code) {
+        mInError = true;
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            mDeviceExecutor.execute(obtainRunnable(
+                        CameraDeviceImpl::notifyError, this, code).recycleOnUse());
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private void notifyError(int code) {
+        if (!CameraDeviceImpl.this.isClosed()) {
+            mDeviceCallback.onError(CameraDeviceImpl.this, code);
+        }
+    }
+
+    /**
+     * Called by onDeviceError for handling single-capture failures.
+     */
+    private void onCaptureErrorLocked(int errorCode, CaptureResultExtras resultExtras) {
+
+        final int requestId = resultExtras.getRequestId();
+        final int subsequenceId = resultExtras.getSubsequenceId();
+        final long frameNumber = resultExtras.getFrameNumber();
+        final String errorPhysicalCameraId = resultExtras.getErrorPhysicalCameraId();
+        final CaptureCallbackHolder holder = mCaptureCallbackMap.get(requestId);
+
+        if (holder == null) {
+            Log.e(TAG, String.format("Receive capture error on unknown request ID %d",
+                    requestId));
+            return;
+        }
+
+        final CaptureRequest request = holder.getRequest(subsequenceId);
+
+        Runnable failureDispatch = null;
+        if (errorCode == CameraDeviceCallbacks.ERROR_CAMERA_BUFFER) {
+            // Because 1 stream id could map to multiple surfaces, we need to specify both
+            // streamId and surfaceId.
+            OutputConfiguration config = mConfiguredOutputs.get(
+                    resultExtras.getErrorStreamId());
+            if (config == null) {
+                Log.v(TAG, String.format(
+                        "Stream %d has been removed. Skipping buffer lost callback",
+                        resultExtras.getErrorStreamId()));
+                return;
+            }
+            for (Surface surface : config.getSurfaces()) {
+                if (!request.containsTarget(surface)) {
+                    continue;
+                }
+                if (DEBUG) {
+                    Log.v(TAG, String.format(
+                            "Lost output buffer reported for frame %d, target %s",
+                            frameNumber, surface));
+                }
+                failureDispatch = new Runnable() {
+                    @Override
+                    public void run() {
+                        if (!isClosed()){
+                            holder.getCallback().onCaptureBufferLost(CameraDeviceImpl.this, request,
+                                    surface, frameNumber);
+                        }
+                    }
+                };
+                // Dispatch the failure callback
+                final long ident = Binder.clearCallingIdentity();
+                try {
+                    holder.getExecutor().execute(failureDispatch);
+                } finally {
+                    Binder.restoreCallingIdentity(ident);
+                }
+            }
+        } else {
+            boolean mayHaveBuffers = (errorCode == CameraDeviceCallbacks.ERROR_CAMERA_RESULT);
+
+            // This is only approximate - exact handling needs the camera service and HAL to
+            // disambiguate between request failures to due abort and due to real errors.  For
+            // now, assume that if the session believes we're mid-abort, then the error is due
+            // to abort.
+            int reason = (mCurrentSession != null && mCurrentSession.isAborting()) ?
+                    CaptureFailure.REASON_FLUSHED :
+                    CaptureFailure.REASON_ERROR;
+
+            final CaptureFailure failure = new CaptureFailure(
+                request,
+                reason,
+                /*dropped*/ mayHaveBuffers,
+                requestId,
+                frameNumber,
+                errorPhysicalCameraId);
+
+            failureDispatch = new Runnable() {
+                @Override
+                public void run() {
+                    if (!isClosed()){
+                        holder.getCallback().onCaptureFailed(CameraDeviceImpl.this, request,
+                                failure);
+                    }
+                }
+            };
+
+            // Fire onCaptureSequenceCompleted if appropriate
+            if (DEBUG) {
+                Log.v(TAG, String.format("got error frame %d", frameNumber));
+            }
+            mFrameNumberTracker.updateTracker(frameNumber,
+                    /*error*/true, request.getRequestType());
+            checkAndFireSequenceComplete();
+
+            // Dispatch the failure callback
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                holder.getExecutor().execute(failureDispatch);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+    }
+
+    public void onDeviceIdle() {
+        if (DEBUG) {
+            Log.d(TAG, "Camera now idle");
+        }
+        synchronized(mInterfaceLock) {
+            if (mRemoteDevice == null) return; // Camera already closed
+
+            // Redirect device callback to the offline session in case we are in the middle
+            // of an offline switch
+            if (mOfflineSessionImpl != null) {
+                mOfflineSessionImpl.getCallbacks().onDeviceIdle();
+                return;
+            }
+
+            if (!CameraDeviceImpl.this.mIdle) {
+                final long ident = Binder.clearCallingIdentity();
+                try {
+                    mDeviceExecutor.execute(mCallOnIdle);
+                } finally {
+                    Binder.restoreCallingIdentity(ident);
+                }
+            }
+            mIdle = true;
+        }
+    }
+
     public class CameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub {
 
         @Override
@@ -1988,60 +1708,7 @@
 
         @Override
         public void onDeviceError(final int errorCode, CaptureResultExtras resultExtras) {
-            if (DEBUG) {
-                Log.d(TAG, String.format(
-                        "Device error received, code %d, frame number %d, request ID %d, subseq ID %d",
-                        errorCode, resultExtras.getFrameNumber(), resultExtras.getRequestId(),
-                        resultExtras.getSubsequenceId()));
-            }
-
-            synchronized(mInterfaceLock) {
-                if (mRemoteDevice == null) {
-                    return; // Camera already closed
-                }
-
-                switch (errorCode) {
-                    case ERROR_CAMERA_DISCONNECTED:
-                        final long ident = Binder.clearCallingIdentity();
-                        try {
-                            CameraDeviceImpl.this.mDeviceExecutor.execute(mCallOnDisconnected);
-                        } finally {
-                            Binder.restoreCallingIdentity(ident);
-                        }
-                        break;
-                    case ERROR_CAMERA_REQUEST:
-                    case ERROR_CAMERA_RESULT:
-                    case ERROR_CAMERA_BUFFER:
-                        onCaptureErrorLocked(errorCode, resultExtras);
-                        break;
-                    case ERROR_CAMERA_DEVICE:
-                        scheduleNotifyError(StateCallback.ERROR_CAMERA_DEVICE);
-                        break;
-                    case ERROR_CAMERA_DISABLED:
-                        scheduleNotifyError(StateCallback.ERROR_CAMERA_DISABLED);
-                        break;
-                    default:
-                        Log.e(TAG, "Unknown error from camera device: " + errorCode);
-                        scheduleNotifyError(StateCallback.ERROR_CAMERA_SERVICE);
-                }
-            }
-        }
-
-        private void scheduleNotifyError(int code) {
-            mInError = true;
-            final long ident = Binder.clearCallingIdentity();
-            try {
-                CameraDeviceImpl.this.mDeviceExecutor.execute(obtainRunnable(
-                            CameraDeviceCallbacks::notifyError, this, code).recycleOnUse());
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
-        }
-
-        private void notifyError(int code) {
-            if (!CameraDeviceImpl.this.isClosed()) {
-                mDeviceCallback.onError(CameraDeviceImpl.this, code);
-            }
+            CameraDeviceImpl.this.onDeviceError(errorCode, resultExtras);
         }
 
         @Override
@@ -2057,6 +1724,14 @@
                     return; // Camera already closed
                 }
 
+                // Redirect device callback to the offline session in case we are in the middle
+                // of an offline switch
+                if (mOfflineSessionImpl != null) {
+                    mOfflineSessionImpl.getCallbacks().onRepeatingRequestError(
+                           lastFrameNumber, repeatingRequestId);
+                    return;
+                }
+
                 checkEarlyTriggerSequenceComplete(mRepeatingRequestId, lastFrameNumber,
                         mRepeatingRequestTypes);
                 // Check if there is already a new repeating request
@@ -2069,22 +1744,7 @@
 
         @Override
         public void onDeviceIdle() {
-            if (DEBUG) {
-                Log.d(TAG, "Camera now idle");
-            }
-            synchronized(mInterfaceLock) {
-                if (mRemoteDevice == null) return; // Camera already closed
-
-                if (!CameraDeviceImpl.this.mIdle) {
-                    final long ident = Binder.clearCallingIdentity();
-                    try {
-                        CameraDeviceImpl.this.mDeviceExecutor.execute(mCallOnIdle);
-                    } finally {
-                        Binder.restoreCallingIdentity(ident);
-                    }
-                }
-                CameraDeviceImpl.this.mIdle = true;
-            }
+            CameraDeviceImpl.this.onDeviceIdle();
         }
 
         @Override
@@ -2100,6 +1760,15 @@
             synchronized(mInterfaceLock) {
                 if (mRemoteDevice == null) return; // Camera already closed
 
+
+                // Redirect device callback to the offline session in case we are in the middle
+                // of an offline switch
+                if (mOfflineSessionImpl != null) {
+                    mOfflineSessionImpl.getCallbacks().onCaptureStarted(resultExtras,
+                            timestamp);
+                    return;
+                }
+
                 // Get the callback for this frame ID, if there is one
                 holder = CameraDeviceImpl.this.mCaptureCallbackMap.get(requestId);
 
@@ -2164,6 +1833,15 @@
             synchronized(mInterfaceLock) {
                 if (mRemoteDevice == null) return; // Camera already closed
 
+
+                // Redirect device callback to the offline session in case we are in the middle
+                // of an offline switch
+                if (mOfflineSessionImpl != null) {
+                    mOfflineSessionImpl.getCallbacks().onResultReceived(result, resultExtras,
+                            physicalResults);
+                    return;
+                }
+
                 // TODO: Handle CameraCharacteristics access from CaptureResult correctly.
                 result.set(CameraCharacteristics.LENS_INFO_SHADING_MAP_SIZE,
                         getCharacteristics().get(CameraCharacteristics.LENS_INFO_SHADING_MAP_SIZE));
@@ -2325,6 +2003,13 @@
             }
 
             synchronized(mInterfaceLock) {
+                // Redirect device callback to the offline session in case we are in the middle
+                // of an offline switch
+                if (mOfflineSessionImpl != null) {
+                    mOfflineSessionImpl.getCallbacks().onPrepared(streamId);
+                    return;
+                }
+
                 output = mConfiguredOutputs.get(streamId);
                 sessionCallback = mSessionStateCallback;
             }
@@ -2350,6 +2035,13 @@
             }
 
             synchronized(mInterfaceLock) {
+                // Redirect device callback to the offline session in case we are in the middle
+                // of an offline switch
+                if (mOfflineSessionImpl != null) {
+                    mOfflineSessionImpl.getCallbacks().onRequestQueueEmpty();
+                    return;
+                }
+
                 sessionCallback = mSessionStateCallback;
             }
 
@@ -2358,117 +2050,6 @@
             sessionCallback.onRequestQueueEmpty();
         }
 
-        /**
-         * Called by onDeviceError for handling single-capture failures.
-         */
-        private void onCaptureErrorLocked(int errorCode, CaptureResultExtras resultExtras) {
-
-            final int requestId = resultExtras.getRequestId();
-            final int subsequenceId = resultExtras.getSubsequenceId();
-            final long frameNumber = resultExtras.getFrameNumber();
-            final String errorPhysicalCameraId = resultExtras.getErrorPhysicalCameraId();
-            final CaptureCallbackHolder holder =
-                    CameraDeviceImpl.this.mCaptureCallbackMap.get(requestId);
-
-            if (holder == null) {
-                Log.e(TAG, String.format("Receive capture error on unknown request ID %d",
-                        requestId));
-                return;
-            }
-
-            final CaptureRequest request = holder.getRequest(subsequenceId);
-
-            Runnable failureDispatch = null;
-            if (errorCode == ERROR_CAMERA_BUFFER) {
-                // Because 1 stream id could map to multiple surfaces, we need to specify both
-                // streamId and surfaceId.
-                OutputConfiguration config = mConfiguredOutputs.get(
-                        resultExtras.getErrorStreamId());
-                if (config == null) {
-                    Log.v(TAG, String.format(
-                            "Stream %d has been removed. Skipping buffer lost callback",
-                            resultExtras.getErrorStreamId()));
-                    return;
-                }
-                for (Surface surface : config.getSurfaces()) {
-                    if (!request.containsTarget(surface)) {
-                        continue;
-                    }
-                    if (DEBUG) {
-                        Log.v(TAG, String.format(
-                                "Lost output buffer reported for frame %d, target %s",
-                                frameNumber, surface));
-                    }
-                    failureDispatch = new Runnable() {
-                        @Override
-                        public void run() {
-                            if (!CameraDeviceImpl.this.isClosed()){
-                                holder.getCallback().onCaptureBufferLost(
-                                    CameraDeviceImpl.this,
-                                    request,
-                                    surface,
-                                    frameNumber);
-                            }
-                        }
-                    };
-                    // Dispatch the failure callback
-                    final long ident = Binder.clearCallingIdentity();
-                    try {
-                        holder.getExecutor().execute(failureDispatch);
-                    } finally {
-                        Binder.restoreCallingIdentity(ident);
-                    }
-                }
-            } else {
-                boolean mayHaveBuffers = (errorCode == ERROR_CAMERA_RESULT);
-
-                // This is only approximate - exact handling needs the camera service and HAL to
-                // disambiguate between request failures to due abort and due to real errors.  For
-                // now, assume that if the session believes we're mid-abort, then the error is due
-                // to abort.
-                int reason = (mCurrentSession != null && mCurrentSession.isAborting()) ?
-                        CaptureFailure.REASON_FLUSHED :
-                        CaptureFailure.REASON_ERROR;
-
-                final CaptureFailure failure = new CaptureFailure(
-                    request,
-                    reason,
-                    /*dropped*/ mayHaveBuffers,
-                    requestId,
-                    frameNumber,
-                    errorPhysicalCameraId);
-
-                failureDispatch = new Runnable() {
-                    @Override
-                    public void run() {
-                        if (!CameraDeviceImpl.this.isClosed()){
-                            holder.getCallback().onCaptureFailed(
-                                CameraDeviceImpl.this,
-                                request,
-                                failure);
-                        }
-                    }
-                };
-
-                // Fire onCaptureSequenceCompleted if appropriate
-                if (DEBUG) {
-                    Log.v(TAG, String.format("got error frame %d", frameNumber));
-                }
-                mFrameNumberTracker.updateTracker(frameNumber,
-                        /*error*/true, request.getRequestType());
-                checkAndFireSequenceComplete();
-
-                // Dispatch the failure callback
-                final long ident = Binder.clearCallingIdentity();
-                try {
-                    holder.getExecutor().execute(failureDispatch);
-                } finally {
-                    Binder.restoreCallingIdentity(ident);
-                }
-            }
-
-        }
-
     } // public class CameraDeviceCallbacks
 
     /**
diff --git a/core/java/android/hardware/camera2/impl/CameraOfflineSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraOfflineSessionImpl.java
new file mode 100644
index 0000000..1db377a
--- /dev/null
+++ b/core/java/android/hardware/camera2/impl/CameraOfflineSessionImpl.java
@@ -0,0 +1,840 @@
+/*
+ * Copyright (C) 2019 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 android.hardware.camera2.impl;
+
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.CameraOfflineSession;
+import android.hardware.camera2.CameraOfflineSession.CameraOfflineSessionCallback;
+import android.hardware.camera2.CaptureFailure;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.ICameraDeviceCallbacks;
+import android.hardware.camera2.ICameraOfflineSession;
+import android.hardware.camera2.TotalCaptureResult;
+import android.hardware.camera2.params.InputConfiguration;
+import android.hardware.camera2.params.OutputConfiguration;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.Range;
+import android.util.SparseArray;
+import android.view.Surface;
+
+import java.util.AbstractMap.SimpleEntry;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.Executor;
+
+import static com.android.internal.util.Preconditions.*;
+
+public class CameraOfflineSessionImpl extends CameraOfflineSession
+        implements IBinder.DeathRecipient {
+    private static final String TAG = "CameraOfflineSessionImpl";
+    private static final int REQUEST_ID_NONE = -1;
+    private static final long NANO_PER_SECOND = 1000000000; //ns
+    private final boolean DEBUG = false;
+
+    private ICameraOfflineSession mRemoteSession;
+    private final AtomicBoolean mClosing = new AtomicBoolean();
+
+    private SimpleEntry<Integer, InputConfiguration> mOfflineInput =
+            new SimpleEntry<>(REQUEST_ID_NONE, null);
+    private SparseArray<OutputConfiguration> mOfflineOutputs = new SparseArray<>();
+
+    final Object mInterfaceLock = new Object(); // access from this class and Session only!
+
+    private final String mCameraId;
+    private final CameraCharacteristics mCharacteristics;
+    private final int mTotalPartialCount;
+
+    private final Executor mOfflineExecutor;
+    private final CameraOfflineSessionCallback mOfflineCallback;
+
+    private final CameraDeviceCallbacks mCallbacks = new CameraDeviceCallbacks();
+
+    /**
+     * A list tracking request and its expected last regular/reprocess/zslStill frame
+     * number.
+     */
+    private List<RequestLastFrameNumbersHolder> mOfflineRequestLastFrameNumbersList =
+            new ArrayList<>();
+
+    /**
+     * An object tracking received frame numbers.
+     * Updated when receiving callbacks from ICameraDeviceCallbacks.
+     */
+    private FrameNumberTracker mFrameNumberTracker = new FrameNumberTracker();
+
+    /** map request IDs to callback/request data */
+    private SparseArray<CaptureCallbackHolder> mCaptureCallbackMap =
+            new SparseArray<CaptureCallbackHolder>();
+
+    public CameraOfflineSessionImpl(String cameraId, CameraCharacteristics characteristics,
+            Executor offlineExecutor, CameraOfflineSessionCallback offlineCallback,
+            SparseArray<OutputConfiguration> offlineOutputs,
+            SimpleEntry<Integer, InputConfiguration> offlineInput,
+            FrameNumberTracker frameNumberTracker, SparseArray<CaptureCallbackHolder> callbackMap,
+            List<RequestLastFrameNumbersHolder> frameNumberList) {
+        if ((cameraId == null) || (characteristics == null)) {
+            throw new IllegalArgumentException("Null argument given");
+        }
+
+        mCameraId = cameraId;
+        mCharacteristics = characteristics;
+
+        Integer partialCount =
+                mCharacteristics.get(CameraCharacteristics.REQUEST_PARTIAL_RESULT_COUNT);
+        if (partialCount == null) {
+            // 1 means partial result is not supported.
+            mTotalPartialCount = 1;
+        } else {
+            mTotalPartialCount = partialCount;
+        }
+
+        mOfflineRequestLastFrameNumbersList.addAll(frameNumberList);
+        mFrameNumberTracker = frameNumberTracker;
+        mCaptureCallbackMap = callbackMap;
+        mOfflineOutputs = offlineOutputs;
+        mOfflineInput = offlineInput;
+        mOfflineExecutor = checkNotNull(offlineExecutor, "offline executor must not be null");
+        mOfflineCallback = checkNotNull(offlineCallback, "offline callback must not be null");
+
+    }
+
+    public CameraDeviceCallbacks getCallbacks() {
+        return mCallbacks;
+    }
+
+    public class CameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub {
+        @Override
+        public IBinder asBinder() {
+            return this;
+        }
+
+        @Override
+        public void onDeviceError(final int errorCode, CaptureResultExtras resultExtras) {
+            synchronized(mInterfaceLock) {
+                if (mRemoteSession == null) {
+                    return; // Camera already closed
+                }
+
+                switch (errorCode) {
+                    case CameraDeviceCallbacks.ERROR_CAMERA_REQUEST:
+                    case CameraDeviceCallbacks.ERROR_CAMERA_RESULT:
+                    case CameraDeviceCallbacks.ERROR_CAMERA_BUFFER:
+                        onCaptureErrorLocked(errorCode, resultExtras);
+                        break;
+                    default:
+                        Runnable errorDispatch = new Runnable() {
+                            @Override
+                            public void run() {
+                                if (!isClosed()) {
+                                    mOfflineCallback.onError(CameraOfflineSessionImpl.this,
+                                            CameraOfflineSessionCallback.STATUS_INTERNAL_ERROR);
+                                }
+                            }
+                        };
+
+                        final long ident = Binder.clearCallingIdentity();
+                        try {
+                            mOfflineExecutor.execute(errorDispatch);
+                        } finally {
+                            Binder.restoreCallingIdentity(ident);
+                        }
+                }
+            }
+        }
+
+        @Override
+        public void onRepeatingRequestError(long lastFrameNumber, int repeatingRequestId) {
+            Log.e(TAG, "Unexpected repeating request error received. Last frame number is " +
+                    lastFrameNumber);
+        }
+
+        @Override
+        public void onDeviceIdle() {
+            synchronized(mInterfaceLock) {
+                Runnable idleDispatch = new Runnable() {
+                    @Override
+                    public void run() {
+                        if (!isClosed()) {
+                            mOfflineCallback.onIdle(CameraOfflineSessionImpl.this);
+                        }
+                    }
+                };
+
+                final long ident = Binder.clearCallingIdentity();
+                try {
+                    mOfflineExecutor.execute(idleDispatch);
+                } finally {
+                    Binder.restoreCallingIdentity(ident);
+                }
+            }
+        }
+
+        @Override
+        public void onCaptureStarted(final CaptureResultExtras resultExtras, final long timestamp) {
+            int requestId = resultExtras.getRequestId();
+            final long frameNumber = resultExtras.getFrameNumber();
+
+            final CaptureCallbackHolder holder;
+
+            synchronized(mInterfaceLock) {
+                if (mRemoteSession == null) return; // Camera already closed
+
+                // Get the callback for this frame ID, if there is one
+                holder = CameraOfflineSessionImpl.this.mCaptureCallbackMap.get(requestId);
+
+                if (holder == null) {
+                    return;
+                }
+
+                final Executor executor = holder.getCallback().getExecutor();
+                if (isClosed() || (executor == null)) return;
+
+                // Dispatch capture start notice
+                final long ident = Binder.clearCallingIdentity();
+                try {
+                    executor.execute(
+                        new Runnable() {
+                            @Override
+                            public void run() {
+                                final CameraCaptureSession.CaptureCallback callback =
+                                        holder.getCallback().getSessionCallback();
+                                if (!CameraOfflineSessionImpl.this.isClosed() &&
+                                        (callback != null)) {
+                                    final int subsequenceId = resultExtras.getSubsequenceId();
+                                    final CaptureRequest request = holder.getRequest(subsequenceId);
+
+                                    if (holder.hasBatchedOutputs()) {
+                                        // Send derived onCaptureStarted for requests within the
+                                        // batch
+                                        final Range<Integer> fpsRange =
+                                                request.get(
+                                                        CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE);
+                                        for (int i = 0; i < holder.getRequestCount(); i++) {
+                                            final CaptureRequest cbRequest = holder.getRequest(i);
+                                            final long cbTimestamp =
+                                                        timestamp - (subsequenceId - i) *
+                                                        NANO_PER_SECOND/fpsRange.getUpper();
+                                            final long cbFrameNumber =
+                                                    frameNumber - (subsequenceId - i);
+                                            callback.onCaptureStarted(CameraOfflineSessionImpl.this,
+                                                    cbRequest, cbTimestamp, cbFrameNumber);
+                                        }
+                                    } else {
+                                        callback.onCaptureStarted(CameraOfflineSessionImpl.this,
+                                                holder.getRequest(
+                                                    resultExtras.getSubsequenceId()),
+                                                timestamp, frameNumber);
+                                    }
+                                }
+                            }
+                        });
+                } finally {
+                    Binder.restoreCallingIdentity(ident);
+                }
+            }
+        }
+
+        @Override
+        public void onResultReceived(CameraMetadataNative result,
+                CaptureResultExtras resultExtras, PhysicalCaptureResultInfo physicalResults[])
+                throws RemoteException {
+
+            int requestId = resultExtras.getRequestId();
+            long frameNumber = resultExtras.getFrameNumber();
+
+            synchronized(mInterfaceLock) {
+                if (mRemoteSession == null) return; // Camera already closed
+
+                // TODO: Handle CameraCharacteristics access from CaptureResult correctly.
+                result.set(CameraCharacteristics.LENS_INFO_SHADING_MAP_SIZE,
+                        mCharacteristics.get(CameraCharacteristics.LENS_INFO_SHADING_MAP_SIZE));
+
+                final CaptureCallbackHolder holder =
+                        CameraOfflineSessionImpl.this.mCaptureCallbackMap.get(requestId);
+                final CaptureRequest request = holder.getRequest(resultExtras.getSubsequenceId());
+
+                boolean isPartialResult =
+                        (resultExtras.getPartialResultCount() < mTotalPartialCount);
+                int requestType = request.getRequestType();
+
+                // Check if we have a callback for this
+                if (holder == null) {
+                    mFrameNumberTracker.updateTracker(frameNumber, /*result*/null, isPartialResult,
+                            requestType);
+
+                    return;
+                }
+
+                if (isClosed()) {
+                    mFrameNumberTracker.updateTracker(frameNumber, /*result*/null, isPartialResult,
+                            requestType);
+                    return;
+                }
+
+
+                Runnable resultDispatch = null;
+
+                CaptureResult finalResult;
+                // Make a copy of the native metadata before it gets moved to a CaptureResult
+                // object.
+                final CameraMetadataNative resultCopy;
+                if (holder.hasBatchedOutputs()) {
+                    resultCopy = new CameraMetadataNative(result);
+                } else {
+                    resultCopy = null;
+                }
+
+                final Executor executor = holder.getCallback().getExecutor();
+                // Either send a partial result or the final capture completed result
+                if (isPartialResult) {
+                    final CaptureResult resultAsCapture =
+                            new CaptureResult(result, request, resultExtras);
+                    // Partial result
+                    resultDispatch = new Runnable() {
+                        @Override
+                        public void run() {
+                            final CameraCaptureSession.CaptureCallback callback =
+                                    holder.getCallback().getSessionCallback();
+                            if (!CameraOfflineSessionImpl.this.isClosed() && (callback != null)) {
+                                if (holder.hasBatchedOutputs()) {
+                                    // Send derived onCaptureProgressed for requests within
+                                    // the batch.
+                                    for (int i = 0; i < holder.getRequestCount(); i++) {
+                                        CameraMetadataNative resultLocal =
+                                                new CameraMetadataNative(resultCopy);
+                                        final CaptureResult resultInBatch = new CaptureResult(
+                                                resultLocal, holder.getRequest(i), resultExtras);
+
+                                        final CaptureRequest cbRequest = holder.getRequest(i);
+                                        callback.onCaptureProgressed(CameraOfflineSessionImpl.this,
+                                                cbRequest, resultInBatch);
+                                    }
+                                } else {
+                                    callback.onCaptureProgressed(CameraOfflineSessionImpl.this,
+                                            request, resultAsCapture);
+                                }
+                            }
+                        }
+                    };
+                    finalResult = resultAsCapture;
+                } else {
+                    List<CaptureResult> partialResults =
+                            mFrameNumberTracker.popPartialResults(frameNumber);
+
+                    final long sensorTimestamp =
+                            result.get(CaptureResult.SENSOR_TIMESTAMP);
+                    final Range<Integer> fpsRange =
+                            request.get(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE);
+                    final int subsequenceId = resultExtras.getSubsequenceId();
+                    final TotalCaptureResult resultAsCapture = new TotalCaptureResult(result,
+                            request, resultExtras, partialResults, holder.getSessionId(),
+                            physicalResults);
+                    // Final capture result
+                    resultDispatch = new Runnable() {
+                        @Override
+                        public void run() {
+                            final CameraCaptureSession.CaptureCallback callback =
+                                    holder.getCallback().getSessionCallback();
+                            if (!CameraOfflineSessionImpl.this.isClosed() && (callback != null)) {
+                                if (holder.hasBatchedOutputs()) {
+                                    // Send derived onCaptureCompleted for requests within
+                                    // the batch.
+                                    for (int i = 0; i < holder.getRequestCount(); i++) {
+                                        resultCopy.set(CaptureResult.SENSOR_TIMESTAMP,
+                                                sensorTimestamp - (subsequenceId - i) *
+                                                NANO_PER_SECOND/fpsRange.getUpper());
+                                        CameraMetadataNative resultLocal =
+                                                new CameraMetadataNative(resultCopy);
+                                        // No logical multi-camera support for batched output mode.
+                                        TotalCaptureResult resultInBatch = new TotalCaptureResult(
+                                            resultLocal, holder.getRequest(i), resultExtras,
+                                            partialResults, holder.getSessionId(),
+                                            new PhysicalCaptureResultInfo[0]);
+
+                                        final CaptureRequest cbRequest = holder.getRequest(i);
+                                        callback.onCaptureCompleted(CameraOfflineSessionImpl.this,
+                                                cbRequest, resultInBatch);
+                                    }
+                                } else {
+                                    callback.onCaptureCompleted(CameraOfflineSessionImpl.this,
+                                            request, resultAsCapture);
+                                }
+                            }
+                        }
+                    };
+                    finalResult = resultAsCapture;
+                }
+
+                if (executor != null) {
+                    final long ident = Binder.clearCallingIdentity();
+                    try {
+                        executor.execute(resultDispatch);
+                    } finally {
+                        Binder.restoreCallingIdentity(ident);
+                    }
+                }
+
+                // Collect the partials for a total result; or mark the frame as totally completed
+                mFrameNumberTracker.updateTracker(frameNumber, finalResult, isPartialResult,
+                        requestType);
+
+                // Fire onCaptureSequenceCompleted
+                if (!isPartialResult) {
+                    checkAndFireSequenceComplete();
+                }
+            }
+        }
+
+        @Override
+        public void onPrepared(int streamId) {
+            Log.e(TAG, "Unexpected stream " + streamId + " is prepared");
+        }
+
+        @Override
+        public void onRequestQueueEmpty() {
+            // No-op during offline mode
+            Log.v(TAG, "onRequestQueueEmpty");
+        }
+
+        /**
+         * Called by onDeviceError for handling single-capture failures.
+         */
+        private void onCaptureErrorLocked(int errorCode, CaptureResultExtras resultExtras) {
+            final int requestId = resultExtras.getRequestId();
+            final int subsequenceId = resultExtras.getSubsequenceId();
+            final long frameNumber = resultExtras.getFrameNumber();
+            final String errorPhysicalCameraId = resultExtras.getErrorPhysicalCameraId();
+            final CaptureCallbackHolder holder =
+                    CameraOfflineSessionImpl.this.mCaptureCallbackMap.get(requestId);
+
+            if (holder == null) {
+                Log.e(TAG, String.format("Receive capture error on unknown request ID %d",
+                        requestId));
+                return;
+            }
+
+            final CaptureRequest request = holder.getRequest(subsequenceId);
+
+            Runnable failureDispatch = null;
+            if (errorCode == ERROR_CAMERA_BUFFER) {
+                // Because 1 stream id could map to multiple surfaces, we need to specify both
+                // streamId and surfaceId.
+                OutputConfiguration config = mOfflineOutputs.get(
+                        resultExtras.getErrorStreamId());
+                if (config == null) {
+                    Log.v(TAG, String.format(
+                            "Stream %d has been removed. Skipping buffer lost callback",
+                            resultExtras.getErrorStreamId()));
+                    return;
+                }
+                for (Surface surface : config.getSurfaces()) {
+                    if (!request.containsTarget(surface)) {
+                        continue;
+                    }
+                    final Executor executor = holder.getCallback().getExecutor();
+                    failureDispatch = new Runnable() {
+                        @Override
+                        public void run() {
+                            final CameraCaptureSession.CaptureCallback callback =
+                                    holder.getCallback().getSessionCallback();
+                            if (!CameraOfflineSessionImpl.this.isClosed() && (callback != null)) {
+                                callback.onCaptureBufferLost( CameraOfflineSessionImpl.this,
+                                        request, surface, frameNumber);
+                            }
+                        }
+                    };
+                    if (executor != null) {
+                        // Dispatch the failure callback
+                        final long ident = Binder.clearCallingIdentity();
+                        try {
+                            executor.execute(failureDispatch);
+                        } finally {
+                            Binder.restoreCallingIdentity(ident);
+                        }
+                    }
+                }
+            } else {
+                boolean mayHaveBuffers = (errorCode == ERROR_CAMERA_RESULT);
+                int reason = CaptureFailure.REASON_ERROR;
+
+                final CaptureFailure failure = new CaptureFailure(
+                    request,
+                    reason,
+                    /*dropped*/ mayHaveBuffers,
+                    requestId,
+                    frameNumber,
+                    errorPhysicalCameraId);
+
+                final Executor executor = holder.getCallback().getExecutor();
+                failureDispatch = new Runnable() {
+                    @Override
+                    public void run() {
+                        final CameraCaptureSession.CaptureCallback callback =
+                                holder.getCallback().getSessionCallback();
+                        if (!CameraOfflineSessionImpl.this.isClosed() && (callback != null)) {
+                            callback.onCaptureFailed(CameraOfflineSessionImpl.this, request,
+                                    failure);
+                        }
+                    }
+                };
+
+                // Fire onCaptureSequenceCompleted if appropriate
+                mFrameNumberTracker.updateTracker(frameNumber,
+                        /*error*/true, request.getRequestType());
+                checkAndFireSequenceComplete();
+
+                if (executor != null) {
+                    // Dispatch the failure callback
+                    final long ident = Binder.clearCallingIdentity();
+                    try {
+                        executor.execute(failureDispatch);
+                    } finally {
+                        Binder.restoreCallingIdentity(ident);
+                    }
+                }
+            }
+
+        }
+
+    }
+
+    private void checkAndFireSequenceComplete() {
+        long completedFrameNumber = mFrameNumberTracker.getCompletedFrameNumber();
+        long completedReprocessFrameNumber = mFrameNumberTracker.getCompletedReprocessFrameNumber();
+        long completedZslStillFrameNumber = mFrameNumberTracker.getCompletedZslStillFrameNumber();
+        Iterator<RequestLastFrameNumbersHolder> iter =
+                mOfflineRequestLastFrameNumbersList.iterator();
+        while (iter.hasNext()) {
+            final RequestLastFrameNumbersHolder requestLastFrameNumbers = iter.next();
+            boolean sequenceCompleted = false;
+            final int requestId = requestLastFrameNumbers.getRequestId();
+            final CaptureCallbackHolder holder;
+            final Executor executor;
+            final CameraCaptureSession.CaptureCallback callback;
+            synchronized(mInterfaceLock) {
+                if (mRemoteSession == null) {
+                    Log.w(TAG, "Camera closed while checking sequences");
+                    return;
+                }
+
+                int index = mCaptureCallbackMap.indexOfKey(requestId);
+                holder = (index >= 0) ?
+                        mCaptureCallbackMap.valueAt(index) : null;
+                if (holder != null) {
+                    long lastRegularFrameNumber =
+                            requestLastFrameNumbers.getLastRegularFrameNumber();
+                    long lastReprocessFrameNumber =
+                            requestLastFrameNumbers.getLastReprocessFrameNumber();
+                    long lastZslStillFrameNumber =
+                            requestLastFrameNumbers.getLastZslStillFrameNumber();
+                    executor = holder.getCallback().getExecutor();
+                    callback = holder.getCallback().getSessionCallback();
+                    // check if it's okay to remove request from mCaptureCallbackMap
+                    if (lastRegularFrameNumber <= completedFrameNumber
+                            && lastReprocessFrameNumber <= completedReprocessFrameNumber
+                            && lastZslStillFrameNumber <= completedZslStillFrameNumber) {
+                        sequenceCompleted = true;
+                        mCaptureCallbackMap.removeAt(index);
+                    }
+                } else {
+                    executor = null;
+                    callback = null;
+                }
+            }
+
+            // If no callback is registered for this requestId or sequence completed, remove it
+            // from the frame number->request pair because it's not needed anymore.
+            if (holder == null || sequenceCompleted) {
+                iter.remove();
+            }
+
+            // Call onCaptureSequenceCompleted
+            if ((sequenceCompleted) && (callback != null) && (executor == null)) {
+                Runnable resultDispatch = new Runnable() {
+                    @Override
+                    public void run() {
+                        if (!isClosed()) {
+                            callback.onCaptureSequenceCompleted(CameraOfflineSessionImpl.this,
+                                    requestId, requestLastFrameNumbers.getLastFrameNumber());
+                        }
+                    }
+                };
+
+                final long ident = Binder.clearCallingIdentity();
+                try {
+                    executor.execute(resultDispatch);
+                } finally {
+                    Binder.restoreCallingIdentity(ident);
+                }
+            }
+        }
+    }
+
+    public void notifyFailedSwitch() {
+        synchronized(mInterfaceLock) {
+            Runnable switchFailDispatch = new Runnable() {
+                @Override
+                public void run() {
+                    mOfflineCallback.onSwitchFailed(CameraOfflineSessionImpl.this);
+                }
+            };
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                mOfflineExecutor.execute(switchFailDispatch);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+    }
+
+    /**
+     * Set remote session.
+     *
+     */
+    public void setRemoteSession(ICameraOfflineSession remoteSession) throws CameraAccessException {
+        synchronized(mInterfaceLock) {
+            if (remoteSession == null) {
+                notifyFailedSwitch();
+                return;
+            }
+
+            mRemoteSession = remoteSession;
+
+            IBinder remoteSessionBinder = remoteSession.asBinder();
+            if (remoteSessionBinder == null) {
+                throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
+                        "The camera offline session has encountered a serious error");
+            }
+
+            try {
+                remoteSessionBinder.linkToDeath(this, /*flag*/ 0);
+            } catch (RemoteException e) {
+                throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
+                        "The camera offline session has encountered a serious error");
+            }
+
+            Runnable readyDispatch = new Runnable() {
+                @Override
+                public void run() {
+                    if (!isClosed()) {
+                        mOfflineCallback.onReady(CameraOfflineSessionImpl.this);
+                    }
+                }
+            };
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                mOfflineExecutor.execute(readyDispatch);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+    }
+
+    /** Whether the offline session has started to close (may not yet have finished) */
+    private boolean isClosed() {
+        return mClosing.get();
+    }
+
+    private void disconnect() {
+        synchronized (mInterfaceLock) {
+            if (mClosing.getAndSet(true)) {
+                return;
+            }
+
+            if (mRemoteSession != null) {
+                mRemoteSession.asBinder().unlinkToDeath(this, /*flags*/0);
+
+                try {
+                    mRemoteSession.disconnect();
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Exception while disconnecting from offline session: ", e);
+                }
+            } else {
+                throw new IllegalStateException("Offline session is not yet ready");
+            }
+
+            mRemoteSession = null;
+
+            Runnable closeDispatch = new Runnable() {
+                @Override
+                public void run() {
+                    if (!isClosed()) {
+                        mOfflineCallback.onClosed(CameraOfflineSessionImpl.this);
+                    }
+                }
+            };
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                mOfflineExecutor.execute(closeDispatch);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            disconnect();
+        }
+        finally {
+            super.finalize();
+        }
+    }
+
+    /**
+     * Listener for binder death.
+     *
+     * <p> Handle binder death for ICameraOfflineSession.</p>
+     */
+    @Override
+    public void binderDied() {
+        Log.w(TAG, "CameraOfflineSession on device " + mCameraId + " died unexpectedly");
+        disconnect();
+    }
+
+    @Override
+    public CameraDevice getDevice() {
+        throw new UnsupportedOperationException("Operation not supported in offline mode");
+    }
+
+    @Override
+    public void prepare(Surface surface) throws CameraAccessException {
+        throw new UnsupportedOperationException("Operation not supported in offline mode");
+    }
+
+    @Override
+    public void prepare(int maxCount, Surface surface) throws CameraAccessException {
+        throw new UnsupportedOperationException("Operation not supported in offline mode");
+    }
+
+    @Override
+    public void tearDown(Surface surface) throws CameraAccessException {
+        throw new UnsupportedOperationException("Operation not supported in offline mode");
+    }
+
+    @Override
+    public void finalizeOutputConfigurations(
+            List<OutputConfiguration> outputConfigs) throws CameraAccessException {
+        throw new UnsupportedOperationException("Operation not supported in offline mode");
+    }
+
+    @Override
+    public int capture(CaptureRequest request, CaptureCallback callback,
+            Handler handler) throws CameraAccessException {
+        throw new UnsupportedOperationException("Operation not supported in offline mode");
+    }
+
+    @Override
+    public int captureSingleRequest(CaptureRequest request, Executor executor,
+            CaptureCallback callback) throws CameraAccessException {
+        throw new UnsupportedOperationException("Operation not supported in offline mode");
+    }
+
+    @Override
+    public int captureBurst(List<CaptureRequest> requests, CaptureCallback callback,
+            Handler handler) throws CameraAccessException {
+        throw new UnsupportedOperationException("Operation not supported in offline mode");
+    }
+
+    @Override
+    public int captureBurstRequests(List<CaptureRequest> requests, Executor executor,
+            CaptureCallback callback) throws CameraAccessException {
+        throw new UnsupportedOperationException("Operation not supported in offline mode");
+    }
+
+    @Override
+    public int setRepeatingRequest(CaptureRequest request, CaptureCallback callback,
+            Handler handler) throws CameraAccessException {
+        throw new UnsupportedOperationException("Operation not supported in offline mode");
+    }
+
+    @Override
+    public int setSingleRepeatingRequest(CaptureRequest request, Executor executor,
+            CaptureCallback callback) throws CameraAccessException {
+        throw new UnsupportedOperationException("Operation not supported in offline mode");
+    }
+
+    @Override
+    public int setRepeatingBurst(List<CaptureRequest> requests,
+            CaptureCallback callback, Handler handler) throws CameraAccessException {
+        throw new UnsupportedOperationException("Operation not supported in offline mode");
+    }
+
+    @Override
+    public int setRepeatingBurstRequests(List<CaptureRequest> requests, Executor executor,
+            CaptureCallback callback) throws CameraAccessException {
+        throw new UnsupportedOperationException("Operation not supported in offline mode");
+    }
+
+    @Override
+    public void stopRepeating() throws CameraAccessException {
+        throw new UnsupportedOperationException("Operation not supported in offline mode");
+    }
+
+    @Override
+    public void abortCaptures() throws CameraAccessException {
+        throw new UnsupportedOperationException("Operation not supported in offline mode");
+    }
+
+    @Override
+    public void updateOutputConfiguration(OutputConfiguration config)
+            throws CameraAccessException {
+        throw new UnsupportedOperationException("Operation not supported in offline mode");
+    }
+
+    @Override
+    public boolean isReprocessable() {
+        throw new UnsupportedOperationException("Operation not supported in offline mode");
+    }
+
+    @Override
+    public Surface getInputSurface() {
+        throw new UnsupportedOperationException("Operation not supported in offline mode");
+    }
+
+    @Override
+    public CameraOfflineSession switchToOffline(Collection<Surface> offlineOutputs,
+            Executor executor, CameraOfflineSessionCallback listener) throws CameraAccessException {
+        throw new UnsupportedOperationException("Operation not supported in offline mode");
+    }
+
+    @Override
+    public boolean supportsOfflineProcessing(Surface surface) {
+        throw new UnsupportedOperationException("Operation not supported in offline mode");
+    }
+
+    @Override
+    public void close() {
+        disconnect();
+    }
+}
diff --git a/core/java/android/hardware/camera2/impl/CaptureCallback.java b/core/java/android/hardware/camera2/impl/CaptureCallback.java
new file mode 100644
index 0000000..6defe63
--- /dev/null
+++ b/core/java/android/hardware/camera2/impl/CaptureCallback.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2019 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 android.hardware.camera2.impl;
+
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CaptureFailure;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.TotalCaptureResult;
+import android.view.Surface;
+
+import java.util.concurrent.Executor;
+
+/**
+ * <p>An internal callback for tracking the progress of a {@link CaptureRequest}
+ * submitted to the camera device.</p>
+ */
+public abstract class CaptureCallback {
+
+    private Executor mExecutor;
+    private CameraCaptureSession.CaptureCallback mCallback;
+
+    public CaptureCallback(Executor executor, CameraCaptureSession.CaptureCallback callback) {
+        mExecutor = executor;
+        mCallback = callback;
+    }
+
+    /**
+     * Retrieve callback executor
+     *
+     */
+    public Executor getExecutor() {
+        return mExecutor;
+    }
+
+    /**
+     * Retrieve capture callback
+     *
+     */
+    public CameraCaptureSession.CaptureCallback getSessionCallback() {
+        return mCallback;
+    }
+
+    /**
+     * This method is called when the camera device has started capturing
+     * the output image for the request, at the beginning of image exposure.
+     *
+     * @see android.media.MediaActionSound
+     */
+    public abstract void onCaptureStarted(CameraDevice camera,
+            CaptureRequest request, long timestamp, long frameNumber);
+
+    /**
+     * This method is called when some results from an image capture are
+     * available.
+     *
+     * @hide
+     */
+    public abstract void onCapturePartial(CameraDevice camera,
+            CaptureRequest request, CaptureResult result);
+
+    /**
+     * This method is called when an image capture makes partial forward progress; some
+     * (but not all) results from an image capture are available.
+     *
+     */
+    public abstract void onCaptureProgressed(CameraDevice camera,
+            CaptureRequest request, CaptureResult partialResult);
+
+    /**
+     * This method is called when an image capture has fully completed and all the
+     * result metadata is available.
+     */
+    public abstract void onCaptureCompleted(CameraDevice camera,
+            CaptureRequest request, TotalCaptureResult result);
+
+    /**
+     * This method is called instead of {@link #onCaptureCompleted} when the
+     * camera device failed to produce a {@link CaptureResult} for the
+     * request.
+     */
+    public abstract void onCaptureFailed(CameraDevice camera,
+            CaptureRequest request, CaptureFailure failure);
+
+    /**
+     * This method is called independently of the others in CaptureCallback,
+     * when a capture sequence finishes and all {@link CaptureResult}
+     * or {@link CaptureFailure} for it have been returned via this callback.
+     */
+    public abstract void onCaptureSequenceCompleted(CameraDevice camera,
+            int sequenceId, long frameNumber);
+
+    /**
+     * This method is called independently of the others in CaptureCallback,
+     * when a capture sequence aborts before any {@link CaptureResult}
+     * or {@link CaptureFailure} for it have been returned via this callback.
+     */
+    public abstract void onCaptureSequenceAborted(CameraDevice camera,
+            int sequenceId);
+
+    /**
+     * This method is called independently of the others in CaptureCallback, if an output buffer
+     * is dropped for a particular capture request.
+     *
+     * Loss of metadata is communicated via onCaptureFailed, independently of any buffer loss.
+     */
+    public abstract void onCaptureBufferLost(CameraDevice camera,
+            CaptureRequest request, Surface target, long frameNumber);
+}
diff --git a/core/java/android/hardware/camera2/impl/CaptureCallbackHolder.java b/core/java/android/hardware/camera2/impl/CaptureCallbackHolder.java
new file mode 100644
index 0000000..01c3890
--- /dev/null
+++ b/core/java/android/hardware/camera2/impl/CaptureCallbackHolder.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2019 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 android.hardware.camera2.impl;
+
+import android.hardware.camera2.CaptureRequest;
+import android.view.Surface;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.Executor;
+
+public class CaptureCallbackHolder {
+
+    private final boolean mRepeating;
+    private final CaptureCallback mCallback;
+    private final List<CaptureRequest> mRequestList;
+    private final Executor mExecutor;
+    private final int mSessionId;
+    /**
+     * <p>Determine if the callback holder is for a constrained high speed request list that
+     * expects batched capture results. Capture results will be batched if the request list
+     * is interleaved with preview and video requests. Capture results won't be batched if the
+     * request list only contains preview requests, or if the request doesn't belong to a
+     * constrained high speed list.
+     */
+    private final boolean mHasBatchedOutputs;
+
+    CaptureCallbackHolder(CaptureCallback callback, List<CaptureRequest> requestList,
+            Executor executor, boolean repeating, int sessionId) {
+        if (callback == null || executor == null) {
+            throw new UnsupportedOperationException(
+                "Must have a valid handler and a valid callback");
+        }
+        mRepeating = repeating;
+        mExecutor = executor;
+        mRequestList = new ArrayList<CaptureRequest>(requestList);
+        mCallback = callback;
+        mSessionId = sessionId;
+
+        // Check whether this callback holder is for batched outputs.
+        // The logic here should match createHighSpeedRequestList.
+        boolean hasBatchedOutputs = true;
+        for (int i = 0; i < requestList.size(); i++) {
+            CaptureRequest request = requestList.get(i);
+            if (!request.isPartOfCRequestList()) {
+                hasBatchedOutputs = false;
+                break;
+            }
+            if (i == 0) {
+                Collection<Surface> targets = request.getTargets();
+                if (targets.size() != 2) {
+                    hasBatchedOutputs = false;
+                    break;
+                }
+            }
+        }
+        mHasBatchedOutputs = hasBatchedOutputs;
+    }
+
+    public boolean isRepeating() {
+        return mRepeating;
+    }
+
+    public CaptureCallback getCallback() {
+        return mCallback;
+    }
+
+    public CaptureRequest getRequest(int subsequenceId) {
+        if (subsequenceId >= mRequestList.size()) {
+            throw new IllegalArgumentException(
+                    String.format(
+                            "Requested subsequenceId %d is larger than request list size %d.",
+                            subsequenceId, mRequestList.size()));
+        } else {
+            if (subsequenceId < 0) {
+                throw new IllegalArgumentException(String.format(
+                        "Requested subsequenceId %d is negative", subsequenceId));
+            } else {
+                return mRequestList.get(subsequenceId);
+            }
+        }
+    }
+
+    public CaptureRequest getRequest() {
+        return getRequest(0);
+    }
+
+    public Executor getExecutor() {
+        return mExecutor;
+    }
+
+    public int getSessionId() {
+        return mSessionId;
+    }
+
+    public int getRequestCount() {
+        return mRequestList.size();
+    }
+
+    public boolean hasBatchedOutputs() {
+        return mHasBatchedOutputs;
+    }
+}
diff --git a/core/java/android/hardware/camera2/impl/FrameNumberTracker.java b/core/java/android/hardware/camera2/impl/FrameNumberTracker.java
new file mode 100644
index 0000000..27f8a61
--- /dev/null
+++ b/core/java/android/hardware/camera2/impl/FrameNumberTracker.java
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2019 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 android.hardware.camera2.impl;
+
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.TreeMap;
+
+/**
+ * This class tracks the last frame number for submitted requests.
+ */
+public class FrameNumberTracker {
+    private static final String TAG = "FrameNumberTracker";
+
+    /** the completed frame number for each type of capture results */
+    private long[] mCompletedFrameNumber = new long[CaptureRequest.REQUEST_TYPE_COUNT];
+
+    /** the skipped frame numbers that don't belong to each type of capture results */
+    private final LinkedList<Long>[] mSkippedOtherFrameNumbers =
+            new LinkedList[CaptureRequest.REQUEST_TYPE_COUNT];
+
+    /** the skipped frame numbers that belong to each type of capture results */
+    private final LinkedList<Long>[] mSkippedFrameNumbers =
+            new LinkedList[CaptureRequest.REQUEST_TYPE_COUNT];
+
+    /** frame number -> request type */
+    private final TreeMap<Long, Integer> mFutureErrorMap = new TreeMap<Long, Integer>();
+    /** Map frame numbers to list of partial results */
+    private final HashMap<Long, List<CaptureResult>> mPartialResults = new HashMap<>();
+
+    public FrameNumberTracker() {
+        for (int i = 0; i < CaptureRequest.REQUEST_TYPE_COUNT; i++) {
+            mCompletedFrameNumber[i] = CameraCaptureSession.CaptureCallback.NO_FRAMES_CAPTURED;
+            mSkippedOtherFrameNumbers[i] = new LinkedList<Long>();
+            mSkippedFrameNumbers[i] = new LinkedList<Long>();
+        }
+    }
+
+    private void update() {
+        Iterator iter = mFutureErrorMap.entrySet().iterator();
+        while (iter.hasNext()) {
+            TreeMap.Entry pair = (TreeMap.Entry)iter.next();
+            Long errorFrameNumber = (Long)pair.getKey();
+            int requestType = (int) pair.getValue();
+            Boolean removeError = false;
+            if (errorFrameNumber == mCompletedFrameNumber[requestType] + 1) {
+                mCompletedFrameNumber[requestType] = errorFrameNumber;
+                removeError = true;
+            } else {
+                if (!mSkippedFrameNumbers[requestType].isEmpty()) {
+                    if (errorFrameNumber == mSkippedFrameNumbers[requestType].element()) {
+                        mCompletedFrameNumber[requestType] = errorFrameNumber;
+                        mSkippedFrameNumbers[requestType].remove();
+                        removeError = true;
+                    }
+                } else {
+                    for (int i = 1; i < CaptureRequest.REQUEST_TYPE_COUNT; i++) {
+                        int otherType = (requestType + i) % CaptureRequest.REQUEST_TYPE_COUNT;
+                        if (!mSkippedOtherFrameNumbers[otherType].isEmpty() && errorFrameNumber
+                                == mSkippedOtherFrameNumbers[otherType].element()) {
+                            mCompletedFrameNumber[requestType] = errorFrameNumber;
+                            mSkippedOtherFrameNumbers[otherType].remove();
+                            removeError = true;
+                            break;
+                        }
+                    }
+                }
+            }
+            if (removeError) {
+                iter.remove();
+            }
+        }
+    }
+
+    /**
+     * This function is called every time when a result or an error is received.
+     * @param frameNumber the frame number corresponding to the result or error
+     * @param isError true if it is an error, false if it is not an error
+     * @param requestType the type of capture request: Reprocess, ZslStill, or Regular.
+     */
+    public void updateTracker(long frameNumber, boolean isError, int requestType) {
+        if (isError) {
+            mFutureErrorMap.put(frameNumber, requestType);
+        } else {
+            try {
+                updateCompletedFrameNumber(frameNumber, requestType);
+            } catch (IllegalArgumentException e) {
+                Log.e(TAG, e.getMessage());
+            }
+        }
+        update();
+    }
+
+    /**
+     * This function is called every time a result has been completed.
+     *
+     * <p>It keeps a track of all the partial results already created for a particular
+     * frame number.</p>
+     *
+     * @param frameNumber the frame number corresponding to the result
+     * @param result the total or partial result
+     * @param partial {@true} if the result is partial, {@code false} if total
+     * @param requestType the type of capture request: Reprocess, ZslStill, or Regular.
+     */
+    public void updateTracker(long frameNumber, CaptureResult result, boolean partial,
+            int requestType) {
+        if (!partial) {
+            // Update the total result's frame status as being successful
+            updateTracker(frameNumber, /*isError*/false, requestType);
+            // Don't keep a list of total results, we don't need to track them
+            return;
+        }
+
+        if (result == null) {
+            // Do not record blank results; this also means there will be no total result
+            // so it doesn't matter that the partials were not recorded
+            return;
+        }
+
+        // Partial results must be aggregated in-order for that frame number
+        List<CaptureResult> partials = mPartialResults.get(frameNumber);
+        if (partials == null) {
+            partials = new ArrayList<>();
+            mPartialResults.put(frameNumber, partials);
+        }
+
+        partials.add(result);
+    }
+
+    /**
+     * Attempt to pop off all of the partial results seen so far for the {@code frameNumber}.
+     *
+     * <p>Once popped-off, the partial results are forgotten (unless {@code updateTracker}
+     * is called again with new partials for that frame number).</p>
+     *
+     * @param frameNumber the frame number corresponding to the result
+     * @return a list of partial results for that frame with at least 1 element,
+     *         or {@code null} if there were no partials recorded for that frame
+     */
+    public List<CaptureResult> popPartialResults(long frameNumber) {
+        return mPartialResults.remove(frameNumber);
+    }
+
+    public long getCompletedFrameNumber() {
+        return mCompletedFrameNumber[CaptureRequest.REQUEST_TYPE_REGULAR];
+    }
+
+    public long getCompletedReprocessFrameNumber() {
+        return mCompletedFrameNumber[CaptureRequest.REQUEST_TYPE_REPROCESS];
+    }
+
+    public long getCompletedZslStillFrameNumber() {
+        return mCompletedFrameNumber[CaptureRequest.REQUEST_TYPE_ZSL_STILL];
+    }
+
+    /**
+     * Update the completed frame number for results of 3 categories
+     * (Regular/Reprocess/ZslStill).
+     *
+     * It validates that all previous frames of the same category have arrived.
+     *
+     * If there is a gap since previous frame number of the same category, assume the frames in
+     * the gap are other categories and store them in the skipped frame number queue to check
+     * against when frames of those categories arrive.
+     */
+    private void updateCompletedFrameNumber(long frameNumber,
+            int requestType) throws IllegalArgumentException {
+        if (frameNumber <= mCompletedFrameNumber[requestType]) {
+            throw new IllegalArgumentException("frame number " + frameNumber + " is a repeat");
+        }
+
+        // Assume there are only 3 different types of capture requests.
+        int otherType1 = (requestType + 1) % CaptureRequest.REQUEST_TYPE_COUNT;
+        int otherType2 = (requestType + 2) % CaptureRequest.REQUEST_TYPE_COUNT;
+        long maxOtherFrameNumberSeen =
+                Math.max(mCompletedFrameNumber[otherType1], mCompletedFrameNumber[otherType2]);
+        if (frameNumber < maxOtherFrameNumberSeen) {
+            // if frame number is smaller than completed frame numbers of other categories,
+            // it must be:
+            // - the head of mSkippedFrameNumbers for this category, or
+            // - in one of other mSkippedOtherFrameNumbers
+            if (!mSkippedFrameNumbers[requestType].isEmpty()) {
+                // frame number must be head of current type of mSkippedFrameNumbers if
+                // mSkippedFrameNumbers isn't empty.
+                if (frameNumber < mSkippedFrameNumbers[requestType].element()) {
+                    throw new IllegalArgumentException("frame number " + frameNumber
+                            + " is a repeat");
+                } else if (frameNumber > mSkippedFrameNumbers[requestType].element()) {
+                    throw new IllegalArgumentException("frame number " + frameNumber
+                            + " comes out of order. Expecting "
+                            + mSkippedFrameNumbers[requestType].element());
+                }
+                // frame number matches the head of the skipped frame number queue.
+                mSkippedFrameNumbers[requestType].remove();
+            } else {
+                // frame number must be in one of the other mSkippedOtherFrameNumbers.
+                int index1 = mSkippedOtherFrameNumbers[otherType1].indexOf(frameNumber);
+                int index2 = mSkippedOtherFrameNumbers[otherType2].indexOf(frameNumber);
+                boolean inSkippedOther1 = index1 != -1;
+                boolean inSkippedOther2 = index2 != -1;
+                if (!(inSkippedOther1 ^ inSkippedOther2)) {
+                    throw new IllegalArgumentException("frame number " + frameNumber
+                            + " is a repeat or invalid");
+                }
+
+                // We know the category of frame numbers in skippedOtherFrameNumbers leading up
+                // to the current frame number. Move them into the correct skippedFrameNumbers.
+                LinkedList<Long> srcList, dstList;
+                int index;
+                if (inSkippedOther1) {
+                    srcList = mSkippedOtherFrameNumbers[otherType1];
+                    dstList = mSkippedFrameNumbers[otherType2];
+                    index = index1;
+                } else {
+                    srcList = mSkippedOtherFrameNumbers[otherType2];
+                    dstList = mSkippedFrameNumbers[otherType1];
+                    index = index2;
+                }
+                for (int i = 0; i < index; i++) {
+                    dstList.add(srcList.removeFirst());
+                }
+
+                // Remove current frame number from skippedOtherFrameNumbers
+                srcList.remove();
+            }
+        } else {
+            // there is a gap of unseen frame numbers which should belong to the other
+            // 2 categories. Put all the skipped frame numbers in the queue.
+            for (long i =
+                    Math.max(maxOtherFrameNumberSeen, mCompletedFrameNumber[requestType]) + 1;
+                    i < frameNumber; i++) {
+                mSkippedOtherFrameNumbers[requestType].add(i);
+            }
+        }
+
+        mCompletedFrameNumber[requestType] = frameNumber;
+    }
+}
+
diff --git a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
index 397417b..fa7301b 100644
--- a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
+++ b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
@@ -110,10 +110,10 @@
         }
     }
 
-    public void endConfigure(int operatingMode, CameraMetadataNative sessionParams)
+    public int[] endConfigure(int operatingMode, CameraMetadataNative sessionParams)
            throws CameraAccessException {
         try {
-            mRemoteDevice.endConfigure(operatingMode, (sessionParams == null) ?
+            return mRemoteDevice.endConfigure(operatingMode, (sessionParams == null) ?
                     new CameraMetadataNative() : sessionParams);
         } catch (Throwable t) {
             CameraManager.throwAsPublicException(t);
@@ -251,10 +251,9 @@
     }
 
     public ICameraOfflineSession switchToOffline(ICameraDeviceCallbacks cbs,
-            Surface[] offlineOutputs)
-            throws CameraAccessException {
+            int[] offlineOutputIds) throws CameraAccessException {
         try {
-            return mRemoteDevice.switchToOffline(cbs, offlineOutputs);
+            return mRemoteDevice.switchToOffline(cbs, offlineOutputIds);
         } catch (Throwable t) {
             CameraManager.throwAsPublicException(t);
             throw new UnsupportedOperationException("Unexpected exception", t);
diff --git a/core/java/android/hardware/camera2/impl/RequestLastFrameNumbersHolder.java b/core/java/android/hardware/camera2/impl/RequestLastFrameNumbersHolder.java
new file mode 100644
index 0000000..bd1df9e
--- /dev/null
+++ b/core/java/android/hardware/camera2/impl/RequestLastFrameNumbersHolder.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2019 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 android.hardware.camera2.impl;
+
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.utils.SubmitInfo;
+
+import java.util.List;
+
+/**
+ * This class holds a capture ID and its expected last regular, zslStill, and reprocess
+ * frame number.
+ */
+public class RequestLastFrameNumbersHolder {
+    // request ID
+    private final int mRequestId;
+    // The last regular frame number for this request ID. It's
+    // CaptureCallback.NO_FRAMES_CAPTURED if the request ID has no regular request.
+    private final long mLastRegularFrameNumber;
+    // The last reprocess frame number for this request ID. It's
+    // CaptureCallback.NO_FRAMES_CAPTURED if the request ID has no reprocess request.
+    private final long mLastReprocessFrameNumber;
+    // The last ZSL still capture frame number for this request ID. It's
+    // CaptureCallback.NO_FRAMES_CAPTURED if the request ID has no zsl request.
+    private final long mLastZslStillFrameNumber;
+
+    /**
+     * Create a request-last-frame-numbers holder with a list of requests, request ID, and
+     * the last frame number returned by camera service.
+     */
+    public RequestLastFrameNumbersHolder(List<CaptureRequest> requestList, SubmitInfo requestInfo) {
+        long lastRegularFrameNumber = CameraCaptureSession.CaptureCallback.NO_FRAMES_CAPTURED;
+        long lastReprocessFrameNumber = CameraCaptureSession.CaptureCallback.NO_FRAMES_CAPTURED;
+        long lastZslStillFrameNumber = CameraCaptureSession.CaptureCallback.NO_FRAMES_CAPTURED;
+        long frameNumber = requestInfo.getLastFrameNumber();
+
+        if (requestInfo.getLastFrameNumber() < requestList.size() - 1) {
+            throw new IllegalArgumentException(
+                    "lastFrameNumber: " + requestInfo.getLastFrameNumber() +
+                    " should be at least " + (requestList.size() - 1) + " for the number of " +
+                    " requests in the list: " + requestList.size());
+        }
+
+        // find the last regular, zslStill, and reprocess frame number
+        for (int i = requestList.size() - 1; i >= 0; i--) {
+            CaptureRequest request = requestList.get(i);
+            int requestType = request.getRequestType();
+            if (requestType == CaptureRequest.REQUEST_TYPE_REPROCESS
+                    && lastReprocessFrameNumber ==
+                    CameraCaptureSession.CaptureCallback.NO_FRAMES_CAPTURED) {
+                lastReprocessFrameNumber = frameNumber;
+            } else if (requestType == CaptureRequest.REQUEST_TYPE_ZSL_STILL
+                    && lastZslStillFrameNumber ==
+                    CameraCaptureSession.CaptureCallback.NO_FRAMES_CAPTURED) {
+                lastZslStillFrameNumber = frameNumber;
+            } else if (requestType == CaptureRequest.REQUEST_TYPE_REGULAR
+                    && lastRegularFrameNumber ==
+                    CameraCaptureSession.CaptureCallback.NO_FRAMES_CAPTURED) {
+                lastRegularFrameNumber = frameNumber;
+            }
+
+            if (lastReprocessFrameNumber != CameraCaptureSession.CaptureCallback.NO_FRAMES_CAPTURED
+                    && lastZslStillFrameNumber !=
+                    CameraCaptureSession.CaptureCallback.NO_FRAMES_CAPTURED
+                    && lastRegularFrameNumber !=
+                    CameraCaptureSession.CaptureCallback.NO_FRAMES_CAPTURED) {
+                break;
+            }
+
+            frameNumber--;
+        }
+
+        mLastRegularFrameNumber = lastRegularFrameNumber;
+        mLastReprocessFrameNumber = lastReprocessFrameNumber;
+        mLastZslStillFrameNumber = lastZslStillFrameNumber;
+        mRequestId = requestInfo.getRequestId();
+    }
+
+    /**
+     * Create a request-last-frame-numbers holder with a request ID and last regular/ZslStill
+     * frame number.
+     */
+    RequestLastFrameNumbersHolder(int requestId, long lastFrameNumber,
+            int[] repeatingRequestTypes) {
+        long lastRegularFrameNumber = CameraCaptureSession.CaptureCallback.NO_FRAMES_CAPTURED;
+        long lastZslStillFrameNumber = CameraCaptureSession.CaptureCallback.NO_FRAMES_CAPTURED;
+
+        if (repeatingRequestTypes == null) {
+            throw new IllegalArgumentException(
+                    "repeatingRequest list must not be null");
+        }
+        if (lastFrameNumber < repeatingRequestTypes.length - 1) {
+            throw new IllegalArgumentException(
+                    "lastFrameNumber: " + lastFrameNumber + " should be at least "
+                    + (repeatingRequestTypes.length - 1)
+                    + " for the number of requests in the list: "
+                    + repeatingRequestTypes.length);
+        }
+
+        long frameNumber = lastFrameNumber;
+        for (int i = repeatingRequestTypes.length - 1; i >= 0; i--) {
+            if (repeatingRequestTypes[i] == CaptureRequest.REQUEST_TYPE_ZSL_STILL
+                    && lastZslStillFrameNumber ==
+                    CameraCaptureSession.CaptureCallback.NO_FRAMES_CAPTURED) {
+                lastZslStillFrameNumber = frameNumber;
+            } else if (repeatingRequestTypes[i] == CaptureRequest.REQUEST_TYPE_REGULAR
+                    && lastRegularFrameNumber ==
+                    CameraCaptureSession.CaptureCallback.NO_FRAMES_CAPTURED) {
+                lastRegularFrameNumber = frameNumber;
+            }
+
+            if (lastZslStillFrameNumber != CameraCaptureSession.CaptureCallback.NO_FRAMES_CAPTURED
+                    && lastRegularFrameNumber !=
+                    CameraCaptureSession.CaptureCallback.NO_FRAMES_CAPTURED) {
+                break;
+            }
+
+            frameNumber--;
+        }
+
+        mLastRegularFrameNumber = lastRegularFrameNumber;
+        mLastZslStillFrameNumber = lastZslStillFrameNumber;
+        mLastReprocessFrameNumber = CameraCaptureSession.CaptureCallback.NO_FRAMES_CAPTURED;
+        mRequestId = requestId;
+    }
+
+    /**
+     * Return the last regular frame number. Return CaptureCallback.NO_FRAMES_CAPTURED if
+     * it contains no regular request.
+     */
+    public long getLastRegularFrameNumber() {
+        return mLastRegularFrameNumber;
+    }
+
+    /**
+     * Return the last reprocess frame number. Return CaptureCallback.NO_FRAMES_CAPTURED if
+     * it contains no reprocess request.
+     */
+    public long getLastReprocessFrameNumber() {
+        return mLastReprocessFrameNumber;
+    }
+
+    /**
+     * Return the last ZslStill frame number. Return CaptureCallback.NO_FRAMES_CAPTURED if
+     * it contains no Zsl request.
+     */
+    public long getLastZslStillFrameNumber() {
+        return mLastZslStillFrameNumber;
+    }
+
+    /**
+     * Return the last frame number overall.
+     */
+    public long getLastFrameNumber() {
+        return Math.max(mLastZslStillFrameNumber,
+                Math.max(mLastRegularFrameNumber, mLastReprocessFrameNumber));
+    }
+
+    /**
+     * Return the request ID.
+     */
+    public int getRequestId() {
+        return mRequestId;
+    }
+}
+
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
index 6ab0c29..cf8cab2 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
@@ -541,7 +541,7 @@
     }
 
     @Override
-    public void endConfigure(int operatingMode, CameraMetadataNative sessionParams) {
+    public int[] endConfigure(int operatingMode, CameraMetadataNative sessionParams) {
         if (DEBUG) {
             Log.d(TAG, "endConfigure called.");
         }
@@ -576,6 +576,8 @@
             mConfiguring = false;
         }
         mLegacyDevice.configureOutputs(surfaces);
+
+        return new int[0]; // Offline mode is not supported
     }
 
     @Override
@@ -791,8 +793,8 @@
 
     @Override
     public ICameraOfflineSession switchToOffline(ICameraDeviceCallbacks cbs,
-            Surface[] offlineOutputs) {
-        throw new UnsupportedOperationException("Legacy device does not support switchToOffline");
+            int[] offlineOutputIds) {
+        throw new UnsupportedOperationException("Legacy device does not support offline mode");
     }
 
     @Override
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index 4d5fabb..2a441de 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -221,7 +221,9 @@
                 inputMethod.revokeSession((InputMethodSession)msg.obj);
                 return;
             case DO_SHOW_SOFT_INPUT:
-                inputMethod.showSoftInput(msg.arg1, (ResultReceiver)msg.obj);
+                SomeArgs args = (SomeArgs)msg.obj;
+                inputMethod.showSoftInputWithToken(
+                        msg.arg1, (ResultReceiver) args.arg2, (IBinder) args.arg1);
                 return;
             case DO_HIDE_SOFT_INPUT:
                 inputMethod.hideSoftInput(msg.arg1, (ResultReceiver)msg.obj);
@@ -230,10 +232,11 @@
                 inputMethod.changeInputMethodSubtype((InputMethodSubtype)msg.obj);
                 return;
             case DO_CREATE_INLINE_SUGGESTIONS_REQUEST:
-                SomeArgs args = (SomeArgs) msg.obj;
+                args = (SomeArgs) msg.obj;
                 inputMethod.onCreateInlineSuggestionsRequest((ComponentName) args.arg1,
                         (AutofillId) args.arg2, (IInlineSuggestionsRequestCallback) args.arg3);
                 return;
+
         }
         Log.w(TAG, "Unhandled message code: " + msg.what);
     }
@@ -371,9 +374,9 @@
 
     @BinderThread
     @Override
-    public void showSoftInput(int flags, ResultReceiver resultReceiver) {
-        mCaller.executeOrSendMessage(mCaller.obtainMessageIO(DO_SHOW_SOFT_INPUT,
-                flags, resultReceiver));
+    public void showSoftInput(IBinder showInputToken, int flags, ResultReceiver resultReceiver) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageIOO(DO_SHOW_SOFT_INPUT,
+                flags, showInputToken, resultReceiver));
     }
 
     @BinderThread
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 8e52ee9..81a0d62 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -46,11 +46,13 @@
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.net.Uri;
+import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.SystemClock;
@@ -450,6 +452,16 @@
     @Nullable
     private InlineSuggestionsRequestInfo mInlineSuggestionsRequestInfo = null;
 
+    /**
+     * An opaque {@link Binder} token of window requesting {@link InputMethodImpl#showSoftInput}
+     * The original app window token is passed from client app window.
+     * {@link com.android.server.inputmethod.InputMethodManagerService} creates a unique dummy
+     * token to identify this window.
+     * This dummy token is only valid for a single call to {@link InputMethodImpl#showSoftInput},
+     * after which it is set null until next call.
+     */
+    private IBinder mCurShowInputToken;
+
     private final Handler mHandler = new Handler(Looper.getMainLooper(), null, true);
 
     final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsComputer = info -> {
@@ -491,6 +503,9 @@
      * all of the standard behavior for an input method.
      */
     public class InputMethodImpl extends AbstractInputMethodImpl {
+
+        private boolean mSystemCallingShowSoftInput;
+
         /**
          * {@inheritDoc}
          * @hide
@@ -659,11 +674,33 @@
 
         /**
          * {@inheritDoc}
+         * @hide
+         */
+        @MainThread
+        @Override
+        public void showSoftInputWithToken(int flags, ResultReceiver resultReceiver,
+                IBinder showInputToken) {
+            mSystemCallingShowSoftInput = true;
+            mCurShowInputToken = showInputToken;
+            showSoftInput(flags, resultReceiver);
+            mCurShowInputToken = null;
+            mSystemCallingShowSoftInput = false;
+        }
+
+        /**
+         * {@inheritDoc}
          */
         @MainThread
         @Override
         public void showSoftInput(int flags, ResultReceiver resultReceiver) {
             if (DEBUG) Log.v(TAG, "showSoftInput()");
+            // TODO(b/148086656): Disallow IME developers from calling InputMethodImpl methods.
+            if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.R
+                    && !mSystemCallingShowSoftInput) {
+                Log.e(TAG," IME shouldn't call showSoftInput on itself."
+                        + " Use requestShowSelf(int) itself");
+                return;
+            }
             final boolean wasVisible = mIsPreRendered
                     ? mDecorViewVisible && mWindowVisible : isInputViewShown();
             if (dispatchOnShowInputRequested(flags, false)) {
@@ -698,6 +735,15 @@
         public void changeInputMethodSubtype(InputMethodSubtype subtype) {
             dispatchOnCurrentInputMethodSubtypeChanged(subtype);
         }
+
+        /**
+         * {@inheritDoc}
+         * @hide
+         */
+        @Override
+        public void setCurrentShowInputToken(IBinder showInputToken) {
+            mCurShowInputToken = showInputToken;
+        }
     }
 
     // TODO(b/137800469): Add detailed docs explaining the inline suggestions process.
@@ -2181,7 +2227,7 @@
         if (!isVisibilityAppliedUsingInsetsConsumer()) {
             return;
         }
-        mPrivOps.applyImeVisibility(setVisible);
+        mPrivOps.applyImeVisibility(mCurShowInputToken, setVisible);
     }
 
     private boolean isVisibilityAppliedUsingInsetsConsumer() {
diff --git a/core/java/android/net/CaptivePortalData.aidl b/core/java/android/net/CaptivePortalData.aidl
new file mode 100644
index 0000000..1d57ee7
--- /dev/null
+++ b/core/java/android/net/CaptivePortalData.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2019 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 android.net;
+
+@JavaOnlyStableParcelable parcelable CaptivePortalData;
diff --git a/core/java/android/net/CaptivePortalData.java b/core/java/android/net/CaptivePortalData.java
new file mode 100644
index 0000000..1357803
--- /dev/null
+++ b/core/java/android/net/CaptivePortalData.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2019 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 android.net;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Metadata sent by captive portals, see https://www.ietf.org/id/draft-ietf-capport-api-03.txt.
+ * @hide
+ */
+@SystemApi
+@TestApi
+public final class CaptivePortalData implements Parcelable {
+    private final long mRefreshTimeMillis;
+    @Nullable
+    private final Uri mUserPortalUrl;
+    @Nullable
+    private final Uri mVenueInfoUrl;
+    private final boolean mIsSessionExtendable;
+    private final long mByteLimit;
+    private final long mExpiryTimeMillis;
+    private final boolean mCaptive;
+
+    private CaptivePortalData(long refreshTimeMillis, Uri userPortalUrl, Uri venueInfoUrl,
+            boolean isSessionExtendable, long byteLimit, long expiryTimeMillis, boolean captive) {
+        mRefreshTimeMillis = refreshTimeMillis;
+        mUserPortalUrl = userPortalUrl;
+        mVenueInfoUrl = venueInfoUrl;
+        mIsSessionExtendable = isSessionExtendable;
+        mByteLimit = byteLimit;
+        mExpiryTimeMillis = expiryTimeMillis;
+        mCaptive = captive;
+    }
+
+    private CaptivePortalData(Parcel p) {
+        this(p.readLong(), p.readParcelable(null), p.readParcelable(null), p.readBoolean(),
+                p.readLong(), p.readLong(), p.readBoolean());
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeLong(mRefreshTimeMillis);
+        dest.writeParcelable(mUserPortalUrl, 0);
+        dest.writeParcelable(mVenueInfoUrl, 0);
+        dest.writeBoolean(mIsSessionExtendable);
+        dest.writeLong(mByteLimit);
+        dest.writeLong(mExpiryTimeMillis);
+        dest.writeBoolean(mCaptive);
+    }
+
+    /**
+     * A builder to create new {@link CaptivePortalData}.
+     */
+    public static class Builder {
+        private long mRefreshTime;
+        private Uri mUserPortalUrl;
+        private Uri mVenueInfoUrl;
+        private boolean mIsSessionExtendable;
+        private long mBytesRemaining = -1;
+        private long mExpiryTime = -1;
+        private boolean mCaptive;
+
+        /**
+         * Create an empty builder.
+         */
+        public Builder() {}
+
+        /**
+         * Create a builder copying all data from existing {@link CaptivePortalData}.
+         */
+        public Builder(@Nullable CaptivePortalData data) {
+            if (data == null) return;
+            setRefreshTime(data.mRefreshTimeMillis)
+                    .setUserPortalUrl(data.mUserPortalUrl)
+                    .setVenueInfoUrl(data.mVenueInfoUrl)
+                    .setSessionExtendable(data.mIsSessionExtendable)
+                    .setBytesRemaining(data.mByteLimit)
+                    .setExpiryTime(data.mExpiryTimeMillis)
+                    .setCaptive(data.mCaptive);
+        }
+
+        /**
+         * Set the time at which data was last refreshed, as per {@link System#currentTimeMillis()}.
+         */
+        @NonNull
+        public Builder setRefreshTime(long refreshTime) {
+            mRefreshTime = refreshTime;
+            return this;
+        }
+
+        /**
+         * Set the URL to be used for users to login to the portal, if captive.
+         */
+        @NonNull
+        public Builder setUserPortalUrl(@Nullable Uri userPortalUrl) {
+            mUserPortalUrl = userPortalUrl;
+            return this;
+        }
+
+        /**
+         * Set the URL that can be used by users to view information about the network venue.
+         */
+        @NonNull
+        public Builder setVenueInfoUrl(@Nullable Uri venueInfoUrl) {
+            mVenueInfoUrl = venueInfoUrl;
+            return this;
+        }
+
+        /**
+         * Set whether the portal supports extending a user session on the portal URL page.
+         */
+        @NonNull
+        public Builder setSessionExtendable(boolean sessionExtendable) {
+            mIsSessionExtendable = sessionExtendable;
+            return this;
+        }
+
+        /**
+         * Set the number of bytes remaining on the network before the portal closes.
+         */
+        @NonNull
+        public Builder setBytesRemaining(long bytesRemaining) {
+            mBytesRemaining = bytesRemaining;
+            return this;
+        }
+
+        /**
+         * Set the time at the session will expire, as per {@link System#currentTimeMillis()}.
+         */
+        @NonNull
+        public Builder setExpiryTime(long expiryTime) {
+            mExpiryTime = expiryTime;
+            return this;
+        }
+
+        /**
+         * Set whether the network is captive (portal closed).
+         */
+        @NonNull
+        public Builder setCaptive(boolean captive) {
+            mCaptive = captive;
+            return this;
+        }
+
+        /**
+         * Create a new {@link CaptivePortalData}.
+         */
+        @NonNull
+        public CaptivePortalData build() {
+            return new CaptivePortalData(mRefreshTime, mUserPortalUrl, mVenueInfoUrl,
+                    mIsSessionExtendable, mBytesRemaining, mExpiryTime, mCaptive);
+        }
+    }
+
+    /**
+     * Get the time at which data was last refreshed, as per {@link System#currentTimeMillis()}.
+     */
+    public long getRefreshTimeMillis() {
+        return mRefreshTimeMillis;
+    }
+
+    /**
+     * Get the URL to be used for users to login to the portal, or extend their session if
+     * {@link #isSessionExtendable()} is true.
+     */
+    @Nullable
+    public Uri getUserPortalUrl() {
+        return mUserPortalUrl;
+    }
+
+    /**
+     * Get the URL that can be used by users to view information about the network venue.
+     */
+    @Nullable
+    public Uri getVenueInfoUrl() {
+        return mVenueInfoUrl;
+    }
+
+    /**
+     * Indicates whether the user portal URL can be used to extend sessions, when the user is logged
+     * in and the session has a time or byte limit.
+     */
+    public boolean isSessionExtendable() {
+        return mIsSessionExtendable;
+    }
+
+    /**
+     * Get the remaining bytes on the captive portal session, at the time {@link CaptivePortalData}
+     * was refreshed. This may be different from the limit currently enforced by the portal.
+     * @return The byte limit, or -1 if not set.
+     */
+    public long getByteLimit() {
+        return mByteLimit;
+    }
+
+    /**
+     * Get the time at the session will expire, as per {@link System#currentTimeMillis()}.
+     * @return The expiry time, or -1 if unset.
+     */
+    public long getExpiryTimeMillis() {
+        return mExpiryTimeMillis;
+    }
+
+    /**
+     * Get whether the network is captive (portal closed).
+     */
+    public boolean isCaptive() {
+        return mCaptive;
+    }
+
+    @NonNull
+    public static final Creator<CaptivePortalData> CREATOR = new Creator<CaptivePortalData>() {
+        @Override
+        public CaptivePortalData createFromParcel(Parcel source) {
+            return new CaptivePortalData(source);
+        }
+
+        @Override
+        public CaptivePortalData[] newArray(int size) {
+            return new CaptivePortalData[size];
+        }
+    };
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mRefreshTimeMillis, mUserPortalUrl, mVenueInfoUrl,
+                mIsSessionExtendable, mByteLimit, mExpiryTimeMillis, mCaptive);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof CaptivePortalData)) return false;
+        final CaptivePortalData other = (CaptivePortalData) obj;
+        return mRefreshTimeMillis == other.mRefreshTimeMillis
+                && Objects.equals(mUserPortalUrl, other.mUserPortalUrl)
+                && Objects.equals(mVenueInfoUrl, other.mVenueInfoUrl)
+                && mIsSessionExtendable == other.mIsSessionExtendable
+                && mByteLimit == other.mByteLimit
+                && mExpiryTimeMillis == other.mExpiryTimeMillis
+                && mCaptive == other.mCaptive;
+    }
+
+    @Override
+    public String toString() {
+        return "CaptivePortalData {"
+                + "refreshTime: " + mRefreshTimeMillis
+                + ", userPortalUrl: " + mUserPortalUrl
+                + ", venueInfoUrl: " + mVenueInfoUrl
+                + ", isSessionExtendable: " + mIsSessionExtendable
+                + ", byteLimit: " + mByteLimit
+                + ", expiryTime: " + mExpiryTimeMillis
+                + ", captive: " + mCaptive
+                + "}";
+    }
+}
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index be8e561..e83f5e4 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -72,6 +72,14 @@
     private String mTcpBufferSizes;
     private IpPrefix mNat64Prefix;
     private boolean mWakeOnLanSupported;
+    private Uri mCaptivePortalApiUrl;
+    private CaptivePortalData mCaptivePortalData;
+
+    /**
+     * Indicates whether parceling should preserve fields that are set based on permissions of
+     * the process receiving the {@link LinkProperties}.
+     */
+    private final transient boolean mParcelSensitiveFields;
 
     private static final int MIN_MTU    = 68;
     private static final int MIN_MTU_V6 = 1280;
@@ -146,6 +154,7 @@
      * Constructs a new {@code LinkProperties} with default values.
      */
     public LinkProperties() {
+        mParcelSensitiveFields = false;
     }
 
     /**
@@ -154,26 +163,32 @@
     @SystemApi
     @TestApi
     public LinkProperties(@Nullable LinkProperties source) {
-        if (source != null) {
-            mIfaceName = source.mIfaceName;
-            mLinkAddresses.addAll(source.mLinkAddresses);
-            mDnses.addAll(source.mDnses);
-            mValidatedPrivateDnses.addAll(source.mValidatedPrivateDnses);
-            mUsePrivateDns = source.mUsePrivateDns;
-            mPrivateDnsServerName = source.mPrivateDnsServerName;
-            mPcscfs.addAll(source.mPcscfs);
-            mDomains = source.mDomains;
-            mRoutes.addAll(source.mRoutes);
-            mHttpProxy = (source.mHttpProxy == null) ? null : new ProxyInfo(source.mHttpProxy);
-            for (LinkProperties l: source.mStackedLinks.values()) {
-                addStackedLink(l);
-            }
-            setMtu(source.mMtu);
-            setDhcpServerAddress(source.getDhcpServerAddress());
-            mTcpBufferSizes = source.mTcpBufferSizes;
-            mNat64Prefix = source.mNat64Prefix;
-            mWakeOnLanSupported = source.mWakeOnLanSupported;
+        this(source, false /* parcelSensitiveFields */);
+    }
+
+    private LinkProperties(@Nullable LinkProperties source, boolean parcelSensitiveFields) {
+        mParcelSensitiveFields = parcelSensitiveFields;
+        if (source == null) return;
+        mIfaceName = source.mIfaceName;
+        mLinkAddresses.addAll(source.mLinkAddresses);
+        mDnses.addAll(source.mDnses);
+        mValidatedPrivateDnses.addAll(source.mValidatedPrivateDnses);
+        mUsePrivateDns = source.mUsePrivateDns;
+        mPrivateDnsServerName = source.mPrivateDnsServerName;
+        mPcscfs.addAll(source.mPcscfs);
+        mDomains = source.mDomains;
+        mRoutes.addAll(source.mRoutes);
+        mHttpProxy = (source.mHttpProxy == null) ? null : new ProxyInfo(source.mHttpProxy);
+        for (LinkProperties l: source.mStackedLinks.values()) {
+            addStackedLink(l);
         }
+        setMtu(source.mMtu);
+        setDhcpServerAddress(source.getDhcpServerAddress());
+        mTcpBufferSizes = source.mTcpBufferSizes;
+        mNat64Prefix = source.mNat64Prefix;
+        mWakeOnLanSupported = source.mWakeOnLanSupported;
+        mCaptivePortalApiUrl = source.mCaptivePortalApiUrl;
+        mCaptivePortalData = source.mCaptivePortalData;
     }
 
     /**
@@ -832,6 +847,11 @@
      * Clears this object to its initial state.
      */
     public void clear() {
+        if (mParcelSensitiveFields) {
+            throw new UnsupportedOperationException(
+                    "Cannot clear LinkProperties when parcelSensitiveFields is set");
+        }
+
         mIfaceName = null;
         mLinkAddresses.clear();
         mDnses.clear();
@@ -847,6 +867,8 @@
         mTcpBufferSizes = null;
         mNat64Prefix = null;
         mWakeOnLanSupported = false;
+        mCaptivePortalApiUrl = null;
+        mCaptivePortalData = null;
     }
 
     /**
@@ -917,6 +939,14 @@
             resultJoiner.add(mDhcpServerAddress.toString());
         }
 
+        if (mCaptivePortalApiUrl != null) {
+            resultJoiner.add("CaptivePortalApiUrl: " + mCaptivePortalApiUrl);
+        }
+
+        if (mCaptivePortalData != null) {
+            resultJoiner.add("CaptivePortalData: " + mCaptivePortalData);
+        }
+
         if (mTcpBufferSizes != null) {
             resultJoiner.add("TcpBufferSizes:");
             resultJoiner.add(mTcpBufferSizes);
@@ -1437,6 +1467,28 @@
     }
 
     /**
+     * Compares this {@code LinkProperties}'s CaptivePortalApiUrl against the target.
+     *
+     * @param target LinkProperties to compare.
+     * @return {@code true} if both are identical, {@code false} otherwise.
+     * @hide
+     */
+    public boolean isIdenticalCaptivePortalApiUrl(LinkProperties target) {
+        return Objects.equals(mCaptivePortalApiUrl, target.mCaptivePortalApiUrl);
+    }
+
+    /**
+     * Compares this {@code LinkProperties}'s CaptivePortalData against the target.
+     *
+     * @param target LinkProperties to compare.
+     * @return {@code true} if both are identical, {@code false} otherwise.
+     * @hide
+     */
+    public boolean isIdenticalCaptivePortalData(LinkProperties target) {
+        return Objects.equals(mCaptivePortalData, target.mCaptivePortalData);
+    }
+
+    /**
      * Set whether the network interface supports WakeOnLAN
      *
      * @param supported WakeOnLAN supported value
@@ -1457,6 +1509,73 @@
     }
 
     /**
+     * Set the URL of the captive portal API endpoint to get more information about the network.
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public void setCaptivePortalApiUrl(@Nullable Uri url) {
+        mCaptivePortalApiUrl = url;
+    }
+
+    /**
+     * Get the URL of the captive portal API endpoint to get more information about the network.
+     *
+     * <p>This is null unless the application has
+     * {@link android.Manifest.permission.NETWORK_SETTINGS} or
+     * {@link NetworkStack#PERMISSION_MAINLINE_NETWORK_STACK} permissions, and the network provided
+     * the URL.
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    @Nullable
+    public Uri getCaptivePortalApiUrl() {
+        return mCaptivePortalApiUrl;
+    }
+
+    /**
+     * Set the CaptivePortalData obtained from the captive portal API (RFC7710bis).
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public void setCaptivePortalData(@Nullable CaptivePortalData data) {
+        mCaptivePortalData = data;
+    }
+
+    /**
+     * Get the CaptivePortalData obtained from the captive portal API (RFC7710bis).
+     *
+     * <p>This is null unless the application has
+     * {@link android.Manifest.permission.NETWORK_SETTINGS} or
+     * {@link NetworkStack#PERMISSION_MAINLINE_NETWORK_STACK} permissions.
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    @Nullable
+    public CaptivePortalData getCaptivePortalData() {
+        return mCaptivePortalData;
+    }
+
+    /**
+     * Create a copy of this {@link LinkProperties} that will preserve fields that were set
+     * based on the permissions of the process that received this {@link LinkProperties}.
+     *
+     * <p>By default {@link LinkProperties} does not preserve such fields during parceling, as
+     * they should not be shared outside of the process that receives them without appropriate
+     * checks.
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    @NonNull
+    public LinkProperties makeSensitiveFieldsParcelingCopy() {
+        return new LinkProperties(this, true /* parcelSensitiveFields */);
+    }
+
+    /**
      * Compares this {@code LinkProperties} instance against the target
      * LinkProperties in {@code obj}. Two LinkPropertieses are equal if
      * all their fields are equal in values.
@@ -1495,7 +1614,9 @@
                 && isIdenticalMtu(target)
                 && isIdenticalTcpBufferSizes(target)
                 && isIdenticalNat64Prefix(target)
-                && isIdenticalWakeOnLan(target);
+                && isIdenticalWakeOnLan(target)
+                && isIdenticalCaptivePortalApiUrl(target)
+                && isIdenticalCaptivePortalData(target);
     }
 
     /**
@@ -1593,7 +1714,8 @@
                 + mPcscfs.size() * 67
                 + ((null == mPrivateDnsServerName) ? 0 : mPrivateDnsServerName.hashCode())
                 + Objects.hash(mNat64Prefix)
-                + (mWakeOnLanSupported ? 71 : 0);
+                + (mWakeOnLanSupported ? 71 : 0)
+                + Objects.hash(mCaptivePortalApiUrl, mCaptivePortalData);
     }
 
     /**
@@ -1632,6 +1754,8 @@
         dest.writeList(stackedLinks);
 
         dest.writeBoolean(mWakeOnLanSupported);
+        dest.writeParcelable(mParcelSensitiveFields ? mCaptivePortalApiUrl : null, 0);
+        dest.writeParcelable(mParcelSensitiveFields ? mCaptivePortalData : null, 0);
     }
 
     private static void writeAddresses(@NonNull Parcel dest, @NonNull List<InetAddress> list) {
@@ -1723,6 +1847,9 @@
                     netProp.addStackedLink(stackedLink);
                 }
                 netProp.setWakeOnLanSupported(in.readBoolean());
+
+                netProp.setCaptivePortalApiUrl(in.readParcelable(null));
+                netProp.setCaptivePortalData(in.readParcelable(null));
                 return netProp;
             }
 
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 739e817..738070b 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -1283,6 +1283,7 @@
      * Gets the SSID of this network, or null if none or unknown.
      * @hide
      */
+    @SystemApi
     public @Nullable String getSSID() {
         return mSSID;
     }
diff --git a/core/java/android/net/NetworkFactory.java b/core/java/android/net/NetworkFactory.java
deleted file mode 100644
index e271037..0000000
--- a/core/java/android/net/NetworkFactory.java
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
- * Copyright (C) 2014 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 android.net;
-
-import android.annotation.NonNull;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.Context;
-import android.os.Build;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Messenger;
-import android.util.Log;
-import android.util.SparseArray;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.IndentingPrintWriter;
-import com.android.internal.util.Protocol;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * A NetworkFactory is an entity that creates NetworkAgent objects.
- * The bearers register with ConnectivityService using {@link #register} and
- * their factory will start receiving scored NetworkRequests.  NetworkRequests
- * can be filtered 3 ways: by NetworkCapabilities, by score and more complexly by
- * overridden function.  All of these can be dynamic - changing NetworkCapabilities
- * or score forces re-evaluation of all current requests.
- *
- * If any requests pass the filter some overrideable functions will be called.
- * If the bearer only cares about very simple start/stopNetwork callbacks, those
- * functions can be overridden.  If the bearer needs more interaction, it can
- * override addNetworkRequest and removeNetworkRequest which will give it each
- * request that passes their current filters.
- * @hide
- **/
-public class NetworkFactory extends Handler {
-    /* TODO: delete when all callers have migrated to NetworkProvider IDs. */
-    public static class SerialNumber {
-        // Guard used by no network factory.
-        public static final int NONE = -1;
-        // A hardcoded serial number for NetworkAgents representing VPNs. These agents are
-        // not created by any factory, so they use this constant for clarity instead of NONE.
-        public static final int VPN = -2;
-        private static final AtomicInteger sNetworkFactorySerialNumber = new AtomicInteger(1);
-        /** Returns a unique serial number for a factory. */
-        public static final int nextSerialNumber() {
-            return sNetworkFactorySerialNumber.getAndIncrement();
-        }
-    }
-
-    private static final boolean DBG = true;
-    private static final boolean VDBG = false;
-
-    private static final int BASE = Protocol.BASE_NETWORK_FACTORY;
-    /**
-     * Pass a network request to the bearer.  If the bearer believes it can
-     * satisfy the request it should connect to the network and create a
-     * NetworkAgent.  Once the NetworkAgent is fully functional it will
-     * register itself with ConnectivityService using registerNetworkAgent.
-     * If the bearer cannot immediately satisfy the request (no network,
-     * user disabled the radio, lower-scored network) it should remember
-     * any NetworkRequests it may be able to satisfy in the future.  It may
-     * disregard any that it will never be able to service, for example
-     * those requiring a different bearer.
-     * msg.obj = NetworkRequest
-     * msg.arg1 = score - the score of the network currently satisfying this
-     *            request.  If this bearer knows in advance it cannot
-     *            exceed this score it should not try to connect, holding the request
-     *            for the future.
-     *            Note that subsequent events may give a different (lower
-     *            or higher) score for this request, transmitted to each
-     *            NetworkFactory through additional CMD_REQUEST_NETWORK msgs
-     *            with the same NetworkRequest but an updated score.
-     *            Also, network conditions may change for this bearer
-     *            allowing for a better score in the future.
-     * msg.arg2 = the ID of the NetworkProvider currently responsible for the
-     *            NetworkAgent handling this request, or NetworkProvider.ID_NONE if none.
-     */
-    public static final int CMD_REQUEST_NETWORK = BASE;
-
-    /**
-     * Cancel a network request
-     * msg.obj = NetworkRequest
-     */
-    public static final int CMD_CANCEL_REQUEST = BASE + 1;
-
-    /**
-     * Internally used to set our best-guess score.
-     * msg.arg1 = new score
-     */
-    private static final int CMD_SET_SCORE = BASE + 2;
-
-    /**
-     * Internally used to set our current filter for coarse bandwidth changes with
-     * technology changes.
-     * msg.obj = new filter
-     */
-    private static final int CMD_SET_FILTER = BASE + 3;
-
-    private final Context mContext;
-    private final ArrayList<Message> mPreConnectedQueue = new ArrayList<Message>();
-    private final String LOG_TAG;
-
-    private final SparseArray<NetworkRequestInfo> mNetworkRequests =
-            new SparseArray<NetworkRequestInfo>();
-
-    private int mScore;
-    private NetworkCapabilities mCapabilityFilter;
-
-    private int mRefCount = 0;
-    private Messenger mMessenger = null;
-    private NetworkProvider mProvider = null;
-    private int mProviderId;
-
-    @UnsupportedAppUsage
-    public NetworkFactory(Looper looper, Context context, String logTag,
-            NetworkCapabilities filter) {
-        super(looper);
-        LOG_TAG = logTag;
-        mContext = context;
-        mCapabilityFilter = filter;
-    }
-
-    public void register() {
-        if (mProvider != null) {
-            Log.e(LOG_TAG, "Ignoring attempt to register already-registered NetworkFactory");
-            return;
-        }
-        if (DBG) log("Registering NetworkFactory");
-
-        mProvider = new NetworkProvider(mContext, NetworkFactory.this.getLooper(), LOG_TAG) {
-            @Override
-            public void onNetworkRequested(@NonNull NetworkRequest request, int score,
-                    int servingProviderId) {
-                handleAddRequest((NetworkRequest) request, score, servingProviderId);
-            }
-
-            @Override
-            public void onRequestWithdrawn(@NonNull NetworkRequest request) {
-                handleRemoveRequest(request);
-            }
-        };
-
-        mMessenger = new Messenger(this);
-        mProviderId = ConnectivityManager.from(mContext).registerNetworkProvider(mProvider);
-    }
-
-    public void unregister() {
-        if (mProvider == null) {
-            Log.e(LOG_TAG, "Ignoring attempt to unregister unregistered NetworkFactory");
-            return;
-        }
-        if (DBG) log("Unregistering NetworkFactory");
-
-        ConnectivityManager.from(mContext).unregisterNetworkProvider(mProvider);
-        mProvider = null;
-    }
-
-    @Override
-    public void handleMessage(Message msg) {
-        switch (msg.what) {
-            case CMD_REQUEST_NETWORK: {
-                handleAddRequest((NetworkRequest) msg.obj, msg.arg1, msg.arg2);
-                break;
-            }
-            case CMD_CANCEL_REQUEST: {
-                handleRemoveRequest((NetworkRequest) msg.obj);
-                break;
-            }
-            case CMD_SET_SCORE: {
-                handleSetScore(msg.arg1);
-                break;
-            }
-            case CMD_SET_FILTER: {
-                handleSetFilter((NetworkCapabilities) msg.obj);
-                break;
-            }
-        }
-    }
-
-    private class NetworkRequestInfo {
-        public final NetworkRequest request;
-        public int score;
-        public boolean requested; // do we have a request outstanding, limited by score
-        public int providerId;
-
-        NetworkRequestInfo(NetworkRequest request, int score, int providerId) {
-            this.request = request;
-            this.score = score;
-            this.requested = false;
-            this.providerId = providerId;
-        }
-
-        @Override
-        public String toString() {
-            return "{" + request + ", score=" + score + ", requested=" + requested + "}";
-        }
-    }
-
-    /**
-     * Add a NetworkRequest that the bearer may want to attempt to satisfy.
-     * @see #CMD_REQUEST_NETWORK
-     *
-     * @param request the request to handle.
-     * @param score the score of the NetworkAgent currently satisfying this request.
-     */
-    // TODO : remove this method. It is a stopgap measure to help sheperding a number
-    // of dependent changes that would conflict throughout the automerger graph. Having this
-    // temporarily helps with the process of going through with all these dependent changes across
-    // the entire tree.
-    @VisibleForTesting
-    protected void handleAddRequest(NetworkRequest request, int score) {
-        handleAddRequest(request, score, NetworkProvider.ID_NONE);
-    }
-
-    /**
-     * Add a NetworkRequest that the bearer may want to attempt to satisfy.
-     * @see #CMD_REQUEST_NETWORK
-     *
-     * @param request the request to handle.
-     * @param score the score of the NetworkAgent currently satisfying this request.
-     * @param servingProviderId the ID of the NetworkProvider that created the NetworkAgent
-     *        currently satisfying this request.
-     */
-    @VisibleForTesting
-    protected void handleAddRequest(NetworkRequest request, int score, int servingProviderId) {
-        NetworkRequestInfo n = mNetworkRequests.get(request.requestId);
-        if (n == null) {
-            if (DBG) {
-                log("got request " + request + " with score " + score
-                        + " and providerId " + servingProviderId);
-            }
-            n = new NetworkRequestInfo(request, score, servingProviderId);
-            mNetworkRequests.put(n.request.requestId, n);
-        } else {
-            if (VDBG) {
-                log("new score " + score + " for exisiting request " + request
-                        + " and providerId " + servingProviderId);
-            }
-            n.score = score;
-            n.providerId = servingProviderId;
-        }
-        if (VDBG) log("  my score=" + mScore + ", my filter=" + mCapabilityFilter);
-
-        evalRequest(n);
-    }
-
-    @VisibleForTesting
-    protected void handleRemoveRequest(NetworkRequest request) {
-        NetworkRequestInfo n = mNetworkRequests.get(request.requestId);
-        if (n != null) {
-            mNetworkRequests.remove(request.requestId);
-            if (n.requested) releaseNetworkFor(n.request);
-        }
-    }
-
-    private void handleSetScore(int score) {
-        mScore = score;
-        evalRequests();
-    }
-
-    private void handleSetFilter(NetworkCapabilities netCap) {
-        mCapabilityFilter = netCap;
-        evalRequests();
-    }
-
-    /**
-     * Overridable function to provide complex filtering.
-     * Called for every request every time a new NetworkRequest is seen
-     * and whenever the filterScore or filterNetworkCapabilities change.
-     *
-     * acceptRequest can be overridden to provide complex filter behavior
-     * for the incoming requests
-     *
-     * For output, this class will call {@link #needNetworkFor} and
-     * {@link #releaseNetworkFor} for every request that passes the filters.
-     * If you don't need to see every request, you can leave the base
-     * implementations of those two functions and instead override
-     * {@link #startNetwork} and {@link #stopNetwork}.
-     *
-     * If you want to see every score fluctuation on every request, set
-     * your score filter to a very high number and watch {@link #needNetworkFor}.
-     *
-     * @return {@code true} to accept the request.
-     */
-    public boolean acceptRequest(NetworkRequest request, int score) {
-        return true;
-    }
-
-    private void evalRequest(NetworkRequestInfo n) {
-        if (VDBG) {
-            log("evalRequest");
-            log(" n.requests = " + n.requested);
-            log(" n.score = " + n.score);
-            log(" mScore = " + mScore);
-            log(" n.providerId = " + n.providerId);
-            log(" mProviderId = " + mProviderId);
-        }
-        if (shouldNeedNetworkFor(n)) {
-            if (VDBG) log("  needNetworkFor");
-            needNetworkFor(n.request, n.score);
-            n.requested = true;
-        } else if (shouldReleaseNetworkFor(n)) {
-            if (VDBG) log("  releaseNetworkFor");
-            releaseNetworkFor(n.request);
-            n.requested = false;
-        } else {
-            if (VDBG) log("  done");
-        }
-    }
-
-    private boolean shouldNeedNetworkFor(NetworkRequestInfo n) {
-        // If this request is already tracked, it doesn't qualify for need
-        return !n.requested
-            // If the score of this request is higher or equal to that of this factory and some
-            // other factory is responsible for it, then this factory should not track the request
-            // because it has no hope of satisfying it.
-            && (n.score < mScore || n.providerId == mProviderId)
-            // If this factory can't satisfy the capability needs of this request, then it
-            // should not be tracked.
-            && n.request.networkCapabilities.satisfiedByNetworkCapabilities(mCapabilityFilter)
-            // Finally if the concrete implementation of the factory rejects the request, then
-            // don't track it.
-            && acceptRequest(n.request, n.score);
-    }
-
-    private boolean shouldReleaseNetworkFor(NetworkRequestInfo n) {
-        // Don't release a request that's not tracked.
-        return n.requested
-            // The request should be released if it can't be satisfied by this factory. That
-            // means either of the following conditions are met :
-            // - Its score is too high to be satisfied by this factory and it's not already
-            //   assigned to the factory
-            // - This factory can't satisfy the capability needs of the request
-            // - The concrete implementation of the factory rejects the request
-            && ((n.score > mScore && n.providerId != mProviderId)
-                    || !n.request.networkCapabilities.satisfiedByNetworkCapabilities(
-                            mCapabilityFilter)
-                    || !acceptRequest(n.request, n.score));
-    }
-
-    private void evalRequests() {
-        for (int i = 0; i < mNetworkRequests.size(); i++) {
-            NetworkRequestInfo n = mNetworkRequests.valueAt(i);
-            evalRequest(n);
-        }
-    }
-
-    /**
-     * Post a command, on this NetworkFactory Handler, to re-evaluate all
-     * oustanding requests. Can be called from a factory implementation.
-     */
-    protected void reevaluateAllRequests() {
-        post(() -> {
-            evalRequests();
-        });
-    }
-
-    /**
-     * Can be called by a factory to release a request as unfulfillable: the request will be
-     * removed, and the caller will get a
-     * {@link ConnectivityManager.NetworkCallback#onUnavailable()} callback after this function
-     * returns.
-     *
-     * Note: this should only be called by factory which KNOWS that it is the ONLY factory which
-     * is able to fulfill this request!
-     */
-    protected void releaseRequestAsUnfulfillableByAnyFactory(NetworkRequest r) {
-        post(() -> {
-            if (DBG) log("releaseRequestAsUnfulfillableByAnyFactory: " + r);
-            ConnectivityManager.from(mContext).declareNetworkRequestUnfulfillable(r);
-        });
-    }
-
-    // override to do simple mode (request independent)
-    protected void startNetwork() { }
-    protected void stopNetwork() { }
-
-    // override to do fancier stuff
-    protected void needNetworkFor(NetworkRequest networkRequest, int score) {
-        if (++mRefCount == 1) startNetwork();
-    }
-
-    protected void releaseNetworkFor(NetworkRequest networkRequest) {
-        if (--mRefCount == 0) stopNetwork();
-    }
-
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
-    public void setScoreFilter(int score) {
-        sendMessage(obtainMessage(CMD_SET_SCORE, score, 0));
-    }
-
-    public void setCapabilityFilter(NetworkCapabilities netCap) {
-        sendMessage(obtainMessage(CMD_SET_FILTER, new NetworkCapabilities(netCap)));
-    }
-
-    @VisibleForTesting
-    protected int getRequestCount() {
-        return mNetworkRequests.size();
-    }
-
-    /* TODO: delete when all callers have migrated to NetworkProvider IDs. */
-    public int getSerialNumber() {
-        return mProviderId;
-    }
-
-    public int getProviderId() {
-        return mProviderId;
-    }
-
-    protected void log(String s) {
-        Log.d(LOG_TAG, s);
-    }
-
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
-    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
-        final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
-        pw.println(toString());
-        pw.increaseIndent();
-        for (int i = 0; i < mNetworkRequests.size(); i++) {
-            pw.println(mNetworkRequests.valueAt(i));
-        }
-        pw.decreaseIndent();
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder("{").append(LOG_TAG).append(" - mProviderId=")
-                .append(mProviderId).append(", ScoreFilter=")
-                .append(mScore).append(", Filter=").append(mCapabilityFilter).append(", requests=")
-                .append(mNetworkRequests.size()).append(", refCount=").append(mRefCount)
-                .append("}");
-        return sb.toString();
-    }
-}
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index d0c5363..08fe159 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -17,9 +17,11 @@
 package android.net;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.telephony.Annotation.NetworkType;
 
 import com.android.internal.annotations.VisibleForTesting;
 
@@ -150,10 +152,19 @@
     private boolean mIsRoaming;
 
     /**
-     * @hide
+     * Create a new instance of NetworkInfo.
+     *
+     * This may be useful for apps to write unit tests.
+     *
+     * @param type the legacy type of the network, as one of the ConnectivityManager.TYPE_*
+     *             constants.
+     * @param subtype the subtype if applicable, as one of the TelephonyManager.NETWORK_TYPE_*
+     *                constants.
+     * @param typeName a human-readable string for the network type, or an empty string or null.
+     * @param subtypeName a human-readable string for the subtype, or an empty string or null.
      */
-    @UnsupportedAppUsage
-    public NetworkInfo(int type, int subtype, String typeName, String subtypeName) {
+    public NetworkInfo(int type, @NetworkType int subtype,
+            @Nullable String typeName, @Nullable String subtypeName) {
         if (!ConnectivityManager.isNetworkTypeValid(type)
                 && type != ConnectivityManager.TYPE_NONE) {
             throw new IllegalArgumentException("Invalid network type: " + type);
@@ -462,17 +473,19 @@
 
     /**
      * Sets the fine-grained state of the network.
+     *
+     * This is only useful for testing.
+     *
      * @param detailedState the {@link DetailedState}.
      * @param reason a {@code String} indicating the reason for the state change,
      * if one was supplied. May be {@code null}.
      * @param extraInfo an optional {@code String} providing addditional network state
      * information passed up from the lower networking layers.
      * @deprecated Use {@link NetworkCapabilities} instead.
-     * @hide
      */
     @Deprecated
-    @UnsupportedAppUsage
-    public void setDetailedState(DetailedState detailedState, String reason, String extraInfo) {
+    public void setDetailedState(@NonNull DetailedState detailedState, @Nullable String reason,
+            @Nullable String extraInfo) {
         synchronized (this) {
             this.mDetailedState = detailedState;
             this.mState = stateMap.get(detailedState);
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index e088094..2b9e9fe 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -105,6 +105,11 @@
      */
     private final int mType;
 
+    /**
+     * The maximum transmission unit size for this route.
+     */
+    private final int mMtu;
+
     // Derived data members.
     // TODO: remove these.
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
@@ -133,6 +138,31 @@
     @TestApi
     public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway,
             @Nullable String iface, @RouteType int type) {
+        this(destination, gateway, iface, type, 0);
+    }
+
+    /**
+     * Constructs a RouteInfo object.
+     *
+     * If destination is null, then gateway must be specified and the
+     * constructed route is either the IPv4 default route <code>0.0.0.0</code>
+     * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
+     * route <code>::/0</code> if gateway is an instance of
+     * {@link Inet6Address}.
+     * <p>
+     * destination and gateway may not both be null.
+     *
+     * @param destination the destination prefix
+     * @param gateway the IP address to route packets through
+     * @param iface the interface name to send packets on
+     * @param type the type of this route
+     * @param mtu the maximum transmission unit size for this route
+     *
+     * @hide
+     */
+    @SystemApi
+    public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway,
+            @Nullable String iface, @RouteType int type, int mtu) {
         switch (type) {
             case RTN_UNICAST:
             case RTN_UNREACHABLE:
@@ -162,7 +192,7 @@
             } else {
                 // no destination, no gateway. invalid.
                 throw new IllegalArgumentException("Invalid arguments passed in: " + gateway + "," +
-                                                   destination);
+                        destination);
             }
         }
         // TODO: set mGateway to null if there is no gateway. This is more correct, saves space, and
@@ -177,10 +207,10 @@
         }
         mHasGateway = (!gateway.isAnyLocalAddress());
 
-        if ((destination.getAddress() instanceof Inet4Address &&
-                 (gateway instanceof Inet4Address == false)) ||
-                (destination.getAddress() instanceof Inet6Address &&
-                 (gateway instanceof Inet6Address == false))) {
+        if ((destination.getAddress() instanceof Inet4Address
+                && !(gateway instanceof Inet4Address))
+                || (destination.getAddress() instanceof Inet6Address
+                && !(gateway instanceof Inet6Address))) {
             throw new IllegalArgumentException("address family mismatch in RouteInfo constructor");
         }
         mDestination = destination;  // IpPrefix objects are immutable.
@@ -188,6 +218,7 @@
         mInterface = iface;          // Strings are immutable.
         mType = type;
         mIsHost = isHost();
+        mMtu = mtu;
     }
 
     /**
@@ -374,6 +405,17 @@
     }
 
     /**
+     * Retrieves the MTU size for this route.
+     *
+     * @return The MTU size, or 0 if it has not been set.
+     * @hide
+     */
+    @SystemApi
+    public int getMtu() {
+        return mMtu;
+    }
+
+    /**
      * Indicates if this route is a default route (ie, has no destination specified).
      *
      * @return {@code true} if the destination has a prefix length of 0.
@@ -463,6 +505,7 @@
                 val += " unknown type " + mType;
             }
         }
+        val += " mtu " + mMtu;
         return val;
     }
 
@@ -480,7 +523,7 @@
         return Objects.equals(mDestination, target.getDestination()) &&
                 Objects.equals(mGateway, target.getGateway()) &&
                 Objects.equals(mInterface, target.getInterface()) &&
-                mType == target.getType();
+                mType == target.getType() && mMtu == target.getMtu();
     }
 
     /**
@@ -490,7 +533,7 @@
         return (mDestination.hashCode() * 41)
                 + (mGateway == null ? 0 :mGateway.hashCode() * 47)
                 + (mInterface == null ? 0 :mInterface.hashCode() * 67)
-                + (mType * 71);
+                + (mType * 71) + (mMtu * 89);
     }
 
     /**
@@ -509,6 +552,7 @@
         dest.writeByteArray(gatewayBytes);
         dest.writeString(mInterface);
         dest.writeInt(mType);
+        dest.writeInt(mMtu);
     }
 
     /**
@@ -527,8 +571,9 @@
 
             String iface = in.readString();
             int type = in.readInt();
+            int mtu = in.readInt();
 
-            return new RouteInfo(dest, gateway, iface, type);
+            return new RouteInfo(dest, gateway, iface, type, mtu);
         }
 
         public RouteInfo[] newArray(int size) {
diff --git a/core/java/android/net/Uri.aidl b/core/java/android/net/Uri.aidl
index 6bd3be5..b85f63b 100644
--- a/core/java/android/net/Uri.aidl
+++ b/core/java/android/net/Uri.aidl
@@ -16,4 +16,4 @@
 
 package android.net;
 
-parcelable Uri;
+@JavaOnlyStableParcelable parcelable Uri;
diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java
index 8bb2df0..b9e6ff4 100644
--- a/core/java/android/nfc/Tag.java
+++ b/core/java/android/nfc/Tag.java
@@ -455,12 +455,12 @@
      *
      * @hide
      */
-    public synchronized void setConnectedTechnology(int technology) {
-        if (mConnectedTechnology == -1) {
-            mConnectedTechnology = technology;
-        } else {
-            throw new IllegalStateException("Close other technology first!");
+    public synchronized boolean setConnectedTechnology(int technology) {
+        if (mConnectedTechnology != -1) {
+            return false;
         }
+        mConnectedTechnology = technology;
+        return true;
     }
 
     /**
diff --git a/core/java/android/nfc/tech/BasicTagTechnology.java b/core/java/android/nfc/tech/BasicTagTechnology.java
index b6b347c..ae468fe 100644
--- a/core/java/android/nfc/tech/BasicTagTechnology.java
+++ b/core/java/android/nfc/tech/BasicTagTechnology.java
@@ -75,7 +75,10 @@
 
             if (errorCode == ErrorCodes.SUCCESS) {
                 // Store this in the tag object
-                mTag.setConnectedTechnology(mSelectedTechnology);
+                if (!mTag.setConnectedTechnology(mSelectedTechnology)) {
+                    Log.e(TAG, "Close other technology first!");
+                    throw new IOException("Only one TagTechnology can be connected at a time.");
+                }
                 mIsConnected = true;
             } else if (errorCode == ErrorCodes.ERROR_NOT_SUPPORTED) {
                 throw new UnsupportedOperationException("Connecting to " +
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 185693e..3ae5700 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -80,6 +80,14 @@
 
     // controls whether PowerManager should doze after the screen turns off or not
     void setDozeAfterScreenOff(boolean on);
+    // returns whether ambient display is available on the device.
+    boolean isAmbientDisplayAvailable();
+    // suppresses the current ambient display configuration and disables ambient display.
+    void suppressAmbientDisplay(String token, boolean suppress);
+    // returns whether ambient display is suppressed by the calling app with the given token.
+    boolean isAmbientDisplaySuppressedForToken(String token);
+    // returns whether ambient display is suppressed by any app with any token.
+    boolean isAmbientDisplaySuppressed();
 
     // Forces the system to suspend even if there are held wakelocks.
     boolean forceSuspend();
diff --git a/core/java/android/os/IncidentManager.java b/core/java/android/os/IncidentManager.java
index f6563eb..8dde117 100644
--- a/core/java/android/os/IncidentManager.java
+++ b/core/java/android/os/IncidentManager.java
@@ -36,6 +36,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.Executor;
 
 /**
@@ -426,10 +427,9 @@
      *
      * @see #registerSection
      * @see #unregisterSection
-     *
-     * @hide
      */
     public static class DumpCallback {
+        private int mId;
         private Executor mExecutor;
 
         IIncidentDumpCallback.Stub mBinder = new IIncidentDumpCallback.Stub() {
@@ -437,20 +437,25 @@
             public void onDumpSection(ParcelFileDescriptor pfd) {
                 if (mExecutor != null) {
                     mExecutor.execute(() -> {
-                        DumpCallback.this.onDumpSection(
+                        DumpCallback.this.onDumpSection(mId,
                                 new ParcelFileDescriptor.AutoCloseOutputStream(pfd));
                     });
                 } else {
-                    DumpCallback.this.onDumpSection(
+                    DumpCallback.this.onDumpSection(mId,
                             new ParcelFileDescriptor.AutoCloseOutputStream(pfd));
                 }
             }
         };
 
         /**
-         * Called when incidentd requests to dump this section.
+         * Dump the registered section as a protobuf message to the given OutputStream. Called when
+         * incidentd requests to dump this section.
+         *
+         * @param id  the id of the registered section. The same id used in calling
+         *            {@link #registerSection(int, String, DumpCallback)} will be passed in here.
+         * @param out the OutputStream to write the protobuf message
          */
-        public void onDumpSection(OutputStream out) {
+        public void onDumpSection(int id, @NonNull OutputStream out) {
         }
     }
 
@@ -563,12 +568,20 @@
 
     /**
      * Register a callback to dump an extended incident report section with the given id and name.
-     * The callback function will be invoked when an incident report with all sections or sections
-     * matching the given id is being taken.
      *
-     * @hide
+     * Calling <code>registerSection</code> with a duplicate id will override previous registration.
+     * However, the request must come from the same calling uid.
+     *
+     * @param id       the ID of the extended section. It should be unique system-wide, and be
+     *                 different from IDs of all existing section in
+     *                 frameworks/base/core/proto/android/os/incident.proto.
+     *                 Also see incident.proto for other rules about the ID.
+     * @param name     the name to display in logs and/or stderr when taking an incident report
+     *                 containing this section, mainly for debugging purpose
+     * @param callback the callback function to be invoked when an incident report with all sections
+     *                 or sections matching the given id is being taken
      */
-    public void registerSection(int id, String name, @NonNull DumpCallback callback) {
+    public void registerSection(int id, @NonNull String name, @NonNull DumpCallback callback) {
         registerSection(id, name, mContext.getMainExecutor(), callback);
     }
 
@@ -576,16 +589,27 @@
      * Register a callback to dump an extended incident report section with the given id and name,
      * running on the supplied executor.
      *
-     * @hide
+     * @param id       the ID of the extended section. It should be unique system-wide, and be
+     *                 different from IDs of all existing section in
+     *                 frameworks/base/core/proto/android/os/incident.proto.
+     *                 Also see incident.proto for other rules about the ID.
+     * @param name     the name to display in logs and/or stderr when taking an incident report
+     *                 containing this section, mainly for debugging purpose
+     * @param executor the executor used to run the callback
+     * @param callback the callback function to be invoked when an incident report with all sections
+     *                 or sections matching the given id is being taken
      */
-    public void registerSection(int id, String name, @NonNull @CallbackExecutor Executor executor,
-            @NonNull DumpCallback callback) {
+    public void registerSection(int id, @NonNull String name,
+                @NonNull @CallbackExecutor Executor executor, @NonNull DumpCallback callback) {
+        Objects.requireNonNull(executor, "executor cannot be null");
+        Objects.requireNonNull(callback, "callback cannot be null");
         try {
             if (callback.mExecutor != null) {
                 throw new RuntimeException("Do not reuse DumpCallback objects when calling"
                         + " registerSection");
             }
             callback.mExecutor = executor;
+            callback.mId = id;
             final IIncidentManager service = getIIncidentManagerLocked();
             if (service == null) {
                 Slog.e(TAG, "registerSection can't find incident binder service");
@@ -599,9 +623,7 @@
 
     /**
      * Unregister an extended section dump function. The section must be previously registered with
-     * {@link #registerSection(int, String, DumpCallback)}
-     *
-     * @hide
+     * {@link #registerSection(int, String, DumpCallback)} by the same calling uid.
      */
     public void unregisterSection(int id) {
         try {
@@ -719,7 +741,7 @@
                 throw new RuntimeException("Invalid URI: No "
                         + URI_PARAM_REPORT_ID + " parameter. " + uri);
             }
-        
+
             try {
                 getCompanionServiceLocked().deleteIncidentReports(pkg, cls, id);
             } catch (RemoteException ex) {
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 0414b14..bf13c35 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -1870,6 +1870,77 @@
     }
 
     /**
+     * Returns true if ambient display is available on the device.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_DREAM_STATE)
+    public boolean isAmbientDisplayAvailable() {
+        try {
+            return mService.isAmbientDisplayAvailable();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * If true, suppresses the current ambient display configuration and disables ambient display.
+     *
+     * <p>This method has no effect if {@link #isAmbientDisplayAvailable()} is false.
+     *
+     * @param token A persistable identifier for the ambient display suppression that is unique
+     *              within the calling application.
+     * @param suppress If set to {@code true}, ambient display will be suppressed. If set to
+     *                 {@code false}, ambient display will no longer be suppressed for the given
+     *                 token.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE)
+    public void suppressAmbientDisplay(@NonNull String token, boolean suppress) {
+        try {
+            mService.suppressAmbientDisplay(token, suppress);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns true if ambient display is suppressed by the calling app with the given
+     * {@code token}.
+     *
+     * <p>This method will return false if {@link #isAmbientDisplayAvailable()} is false.
+     *
+     * @param token The identifier of the ambient display suppression.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_DREAM_STATE)
+    public boolean isAmbientDisplaySuppressedForToken(@NonNull String token) {
+        try {
+            return mService.isAmbientDisplaySuppressedForToken(token);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns true if ambient display is suppressed by <em>any</em> app with <em>any</em> token.
+     *
+     * <p>This method will return false if {@link #isAmbientDisplayAvailable()} is false.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_DREAM_STATE)
+    public boolean isAmbientDisplaySuppressed() {
+        try {
+            return mService.isAmbientDisplaySuppressed();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Returns the reason the phone was last shutdown. Calling app must have the
      * {@link android.Manifest.permission#DEVICE_POWER} permission to request this information.
      * @return Reason for shutdown as an int, {@link #SHUTDOWN_REASON_UNKNOWN} if the file could
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 5d80ab6..c7a8474 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -20,14 +20,20 @@
 import android.annotation.Nullable;
 import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
+import android.system.ErrnoException;
 import android.system.Os;
 import android.system.OsConstants;
+import android.system.StructPollfd;
 import android.util.Pair;
 import android.webkit.WebViewZygote;
 
 import dalvik.system.VMRuntime;
 
+import libcore.io.IoUtils;
+
+import java.io.FileDescriptor;
 import java.util.Map;
+import java.util.concurrent.TimeoutException;
 
 /**
  * Tools for managing OS processes.
@@ -487,6 +493,15 @@
     private static long sStartElapsedRealtime;
     private static long sStartUptimeMillis;
 
+    private static final int PIDFD_UNKNOWN = 0;
+    private static final int PIDFD_SUPPORTED = 1;
+    private static final int PIDFD_UNSUPPORTED = 2;
+
+    /**
+     * Whether or not the underlying OS supports pidfd
+     */
+    private static int sPidFdSupported = PIDFD_UNKNOWN;
+
     /**
      * State associated with the zygote process.
      * @hide
@@ -1189,4 +1204,90 @@
         }
 
     }
+
+    /**
+     * Wait for the death of the given process.
+     *
+     * @param pid The process ID to be waited on
+     * @param timeout The maximum time to wait in milliseconds, or -1 to wait forever
+     * @hide
+     */
+    public static void waitForProcessDeath(int pid, int timeout)
+            throws InterruptedException, TimeoutException {
+        FileDescriptor pidfd = null;
+        if (sPidFdSupported == PIDFD_UNKNOWN) {
+            int fd = -1;
+            try {
+                fd = nativePidFdOpen(pid, 0);
+                sPidFdSupported = PIDFD_SUPPORTED;
+            } catch (ErrnoException e) {
+                sPidFdSupported = e.errno != OsConstants.ENOSYS
+                    ? PIDFD_SUPPORTED : PIDFD_UNSUPPORTED;
+            } finally {
+                if (fd >= 0) {
+                    pidfd = new FileDescriptor();
+                    pidfd.setInt$(fd);
+                }
+            }
+        }
+        boolean fallback = sPidFdSupported == PIDFD_UNSUPPORTED;
+        if (!fallback) {
+            try {
+                if (pidfd == null) {
+                    int fd = nativePidFdOpen(pid, 0);
+                    if (fd >= 0) {
+                        pidfd = new FileDescriptor();
+                        pidfd.setInt$(fd);
+                    } else {
+                        fallback = true;
+                    }
+                }
+                if (pidfd != null) {
+                    StructPollfd[] fds = new StructPollfd[] {
+                        new StructPollfd()
+                    };
+                    fds[0].fd = pidfd;
+                    fds[0].events = (short) OsConstants.POLLIN;
+                    fds[0].revents = 0;
+                    fds[0].userData = null;
+                    int res = Os.poll(fds, timeout);
+                    if (res > 0) {
+                        return;
+                    } else if (res == 0) {
+                        throw new TimeoutException();
+                    } else {
+                        // We should get an ErrnoException now
+                    }
+                }
+            } catch (ErrnoException e) {
+                if (e.errno == OsConstants.EINTR) {
+                    throw new InterruptedException();
+                }
+                fallback = true;
+            } finally {
+                if (pidfd != null) {
+                    IoUtils.closeQuietly(pidfd);
+                }
+            }
+        }
+        if (fallback) {
+            boolean infinity = timeout < 0;
+            long now = System.currentTimeMillis();
+            final long end = now + timeout;
+            while (infinity || now < end) {
+                try {
+                    Os.kill(pid, 0);
+                } catch (ErrnoException e) {
+                    if (e.errno == OsConstants.ESRCH) {
+                        return;
+                    }
+                }
+                Thread.sleep(1);
+                now = System.currentTimeMillis();
+            }
+        }
+        throw new TimeoutException();
+    }
+
+    private static native int nativePidFdOpen(int pid, int flags) throws ErrnoException;
 }
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 1453608..bb1c8ed 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -16,6 +16,8 @@
 
 package android.provider;
 
+import static android.annotation.SystemApi.Client.MODULE_APPS;
+
 import static com.android.internal.util.Preconditions.checkCollectionElementsNotNull;
 import static com.android.internal.util.Preconditions.checkCollectionNotEmpty;
 
@@ -24,6 +26,7 @@
 import android.annotation.SystemApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ContentInterface;
+import android.content.ContentProvider;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -47,6 +50,7 @@
 import android.os.Parcelable;
 import android.os.ParcelableException;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.util.Log;
 
 import com.android.internal.util.Preconditions;
@@ -945,6 +949,20 @@
         return getBaseDocumentUriBuilder(authority).appendPath(documentId).build();
     }
 
+    /**
+     * Builds URI as described in {@link #buildDocumentUri(String, String)}, but such that it will
+     * be associated with the given user.
+     *
+     * @hide
+     */
+    @SystemApi(client = MODULE_APPS)
+    @NonNull
+    public static Uri buildDocumentUriAsUser(
+            @NonNull String authority, @NonNull String documentId, @NonNull UserHandle user) {
+        return ContentProvider.maybeAddUserId(
+                buildDocumentUri(authority, documentId), user.getIdentifier());
+    }
+
     /** {@hide} */
     public static Uri buildBaseDocumentUri(String authority) {
         return getBaseDocumentUriBuilder(authority).build();
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 0742a20..c7c3140 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1969,6 +1969,21 @@
             "android.settings.REQUEST_SET_AUTOFILL_SERVICE";
 
     /**
+     * Activity Action: Show screen for controlling the Quick Access Wallet.
+     * <p>
+     * In some cases, a matching Activity may not exist, so ensure you
+     * safeguard against this.
+     * <p>
+     * Input: The Intent's data URI specifies the application package name
+     * to be shown, with the "package" scheme.  That is "package:com.my.app".
+     * <p>
+     * Output: Nothing.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_QUICK_ACCESS_WALLET_SETTINGS =
+            "android.settings.QUICK_ACCESS_WALLET_SETTINGS";
+
+    /**
      * Activity Action: Show screen for controlling which apps have access on volume directories.
      * <p>
      * Input: Nothing.
diff --git a/core/java/android/service/quickaccesswallet/GetWalletCardsCallback.java b/core/java/android/service/quickaccesswallet/GetWalletCardsCallback.java
new file mode 100644
index 0000000..9d210cd
--- /dev/null
+++ b/core/java/android/service/quickaccesswallet/GetWalletCardsCallback.java
@@ -0,0 +1,92 @@
+/*
+ * 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 android.service.quickaccesswallet;
+
+import android.annotation.NonNull;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * Handles response from the {@link QuickAccessWalletService} for {@link GetWalletCardsRequest}
+ */
+public final class GetWalletCardsCallback {
+
+    private static final String TAG = "QAWalletCallback";
+
+    private final IQuickAccessWalletServiceCallbacks mCallback;
+    private final Handler mHandler;
+    private boolean mCalled;
+
+    /**
+     * @hide
+     */
+    GetWalletCardsCallback(IQuickAccessWalletServiceCallbacks callback, Handler handler) {
+        mCallback = callback;
+        mHandler = handler;
+    }
+
+    /**
+     * Notifies the Android System that an {@link QuickAccessWalletService#onWalletCardsRequested}
+     * was successfully handled by the service.
+     *
+     * @param response The response contains the list of {@link WalletCard walletCards} to be shown
+     *                 to the user as well as the index of the card that should initially be
+     *                 presented as the selected card.
+     */
+    public void onSuccess(@NonNull GetWalletCardsResponse response) {
+        mHandler.post(() -> onSuccessInternal(response));
+    }
+
+    /**
+     * Notifies the Android System that an {@link QuickAccessWalletService#onWalletCardsRequested}
+     * could not be handled by the service.
+     *
+     * @param error The error message. <b>Note: </b> this message should <b>not</b> contain PII
+     *              (Personally Identifiable Information, such as username or email address).
+     * @throws IllegalStateException if this method or {@link #onSuccess} was already called.
+     */
+    public void onFailure(@NonNull GetWalletCardsError error) {
+        mHandler.post(() -> onFailureInternal(error));
+    }
+
+    private void onSuccessInternal(GetWalletCardsResponse response) {
+        if (mCalled) {
+            Log.w(TAG, "already called");
+            return;
+        }
+        mCalled = true;
+        try {
+            mCallback.onGetWalletCardsSuccess(response);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error returning wallet cards", e);
+        }
+    }
+
+    private void onFailureInternal(GetWalletCardsError error) {
+        if (mCalled) {
+            Log.w(TAG, "already called");
+            return;
+        }
+        mCalled = true;
+        try {
+            mCallback.onGetWalletCardsFailure(error);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error returning failure message", e);
+        }
+    }
+}
diff --git a/core/java/android/service/quickaccesswallet/GetWalletCardsError.aidl b/core/java/android/service/quickaccesswallet/GetWalletCardsError.aidl
new file mode 100644
index 0000000..847f5ac
--- /dev/null
+++ b/core/java/android/service/quickaccesswallet/GetWalletCardsError.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 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 android.service.quickaccesswallet;
+
+parcelable GetWalletCardsError;
\ No newline at end of file
diff --git a/core/java/android/service/quickaccesswallet/GetWalletCardsError.java b/core/java/android/service/quickaccesswallet/GetWalletCardsError.java
new file mode 100644
index 0000000..527d2b7
--- /dev/null
+++ b/core/java/android/service/quickaccesswallet/GetWalletCardsError.java
@@ -0,0 +1,100 @@
+/*
+ * 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 android.service.quickaccesswallet;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.drawable.Icon;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+/**
+ * Error response for an {@link GetWalletCardsRequest}.
+ */
+public final class GetWalletCardsError implements Parcelable {
+
+    private final Icon mIcon;
+    private final CharSequence mMessage;
+
+    /**
+     * Construct a new error response. If provided, the icon and message will be displayed to the
+     * user.
+     *
+     * @param icon    an icon to be shown to the user next to the message. Optional.
+     * @param message message to be shown to the user. Optional.
+     */
+    public GetWalletCardsError(@Nullable Icon icon, @Nullable CharSequence message) {
+        mIcon = icon;
+        mMessage = message;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        if (mIcon == null) {
+            dest.writeByte((byte) 0);
+        } else {
+            dest.writeByte((byte) 1);
+            mIcon.writeToParcel(dest, flags);
+        }
+        TextUtils.writeToParcel(mMessage, dest, flags);
+    }
+
+    private static GetWalletCardsError readFromParcel(Parcel source) {
+        Icon icon = source.readByte() == 0 ? null : Icon.CREATOR.createFromParcel(source);
+        CharSequence message = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
+        return new GetWalletCardsError(icon, message);
+    }
+
+    @NonNull
+    public static final Creator<GetWalletCardsError> CREATOR =
+            new Creator<GetWalletCardsError>() {
+                @Override
+                public GetWalletCardsError createFromParcel(Parcel source) {
+                    return readFromParcel(source);
+                }
+
+                @Override
+                public GetWalletCardsError[] newArray(int size) {
+                    return new GetWalletCardsError[size];
+                }
+            };
+
+    /**
+     * An icon that may be displayed with the message to provide a visual indication of why cards
+     * could not be provided in the Quick Access Wallet.
+     */
+    @Nullable
+    public Icon getIcon() {
+        return mIcon;
+    }
+
+    /**
+     * A localized message that may be shown to the user in the event that the wallet cards cannot
+     * be retrieved. <b>Note: </b> this message should <b>not</b> contain PII (Personally
+     * Identifiable Information, such as username or email address).
+     */
+    @Nullable
+    public CharSequence getMessage() {
+        return mMessage;
+    }
+}
diff --git a/core/java/android/service/quickaccesswallet/GetWalletCardsRequest.aidl b/core/java/android/service/quickaccesswallet/GetWalletCardsRequest.aidl
new file mode 100644
index 0000000..e70a982
--- /dev/null
+++ b/core/java/android/service/quickaccesswallet/GetWalletCardsRequest.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 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 android.service.quickaccesswallet;
+
+parcelable GetWalletCardsRequest;
\ No newline at end of file
diff --git a/core/java/android/service/quickaccesswallet/GetWalletCardsRequest.java b/core/java/android/service/quickaccesswallet/GetWalletCardsRequest.java
new file mode 100644
index 0000000..2ba448f
--- /dev/null
+++ b/core/java/android/service/quickaccesswallet/GetWalletCardsRequest.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 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 android.service.quickaccesswallet;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Represents a request to a {@link QuickAccessWalletService} for {@link WalletCard walletCards}.
+ * Wallet cards may represent anything that a user might carry in their wallet -- a credit card,
+ * library card, a transit pass, etc. This request contains the desired size of the card images and
+ * icons as well as the maximum number of cards that may be returned in the {@link
+ * GetWalletCardsResponse}.
+ *
+ * <p>Cards may be displayed with an optional icon and label. The icon and label should communicate
+ * the same idea. For example, if a card can be used at an NFC terminal, the icon could be an NFC
+ * icon and the label could inform the user how to interact with the NFC terminal.
+ *
+ * <p>The maximum number of cards that may be displayed in the wallet is provided in {@link
+ * #getMaxCards()}. The {@link QuickAccessWalletService} may provide up to this many cards in the
+ * {@link GetWalletCardsResponse#getWalletCards()}. If the list of cards provided exceeds this
+ * number, some of the cards may not be shown to the user.
+ */
+public final class GetWalletCardsRequest implements Parcelable {
+
+    private final int mCardWidthPx;
+    private final int mCardHeightPx;
+    private final int mIconSizePx;
+    private final int mMaxCards;
+
+    /**
+     * Creates a new GetWalletCardsRequest.
+     *
+     * @param cardWidthPx  The width of the card image in pixels.
+     * @param cardHeightPx The height of the card image in pixels.
+     * @param iconSizePx   The width and height of the optional card icon in pixels.
+     * @param maxCards     The maximum number of cards that may be provided in the response.
+     */
+    public GetWalletCardsRequest(int cardWidthPx, int cardHeightPx, int iconSizePx, int maxCards) {
+        this.mCardWidthPx = cardWidthPx;
+        this.mCardHeightPx = cardHeightPx;
+        this.mIconSizePx = iconSizePx;
+        this.mMaxCards = maxCards;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(mCardWidthPx);
+        dest.writeInt(mCardHeightPx);
+        dest.writeInt(mIconSizePx);
+        dest.writeInt(mMaxCards);
+    }
+
+    @NonNull
+    public static final Creator<GetWalletCardsRequest> CREATOR =
+            new Creator<GetWalletCardsRequest>() {
+                @Override
+                public GetWalletCardsRequest createFromParcel(Parcel source) {
+                    int cardWidthPx = source.readInt();
+                    int cardHeightPx = source.readInt();
+                    int iconSizePx = source.readInt();
+                    int maxCards = source.readInt();
+                    return new GetWalletCardsRequest(cardWidthPx,
+                            cardHeightPx,
+                            iconSizePx,
+                            maxCards);
+                }
+
+                @Override
+                public GetWalletCardsRequest[] newArray(int size) {
+                    return new GetWalletCardsRequest[size];
+                }
+            };
+
+    /**
+     * The desired width of the {@link WalletCard#getCardImage()}, in pixels. The dimensions of the
+     * card image are requested so that it may be rendered without scaling.
+     * <p>
+     * The {@code cardWidthPx} and {@code cardHeightPx} should be applied to the size of the {@link
+     * WalletCard#getCardImage()}. The size of the card image is specified so that it may be
+     * rendered accurately and without distortion caused by scaling.
+     */
+    public int getCardWidthPx() {
+        return mCardWidthPx;
+    }
+
+    /**
+     * The desired height of the {@link WalletCard#getCardImage()}, in pixels. The dimensions of the
+     * card image are requested so that it may be rendered without scaling.
+     */
+    public int getCardHeightPx() {
+        return mCardHeightPx;
+    }
+
+    /**
+     * Wallet cards may be displayed next to an icon. The icon can help to convey additional
+     * information about the state of the card. If the provided icon is a bitmap, its width and
+     * height should equal iconSizePx so that it is rendered without distortion caused by scaling.
+     */
+    public int getIconSizePx() {
+        return mIconSizePx;
+    }
+
+    /**
+     * The maximum size of the {@link GetWalletCardsResponse#getWalletCards()}. If the list of cards
+     * exceeds this number, not all cards may be displayed.
+     */
+    public int getMaxCards() {
+        return mMaxCards;
+    }
+}
diff --git a/core/java/android/service/quickaccesswallet/GetWalletCardsResponse.aidl b/core/java/android/service/quickaccesswallet/GetWalletCardsResponse.aidl
new file mode 100644
index 0000000..b0f25b3
--- /dev/null
+++ b/core/java/android/service/quickaccesswallet/GetWalletCardsResponse.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 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 android.service.quickaccesswallet;
+
+parcelable GetWalletCardsResponse;
\ No newline at end of file
diff --git a/core/java/android/service/quickaccesswallet/GetWalletCardsResponse.java b/core/java/android/service/quickaccesswallet/GetWalletCardsResponse.java
new file mode 100644
index 0000000..996622a
--- /dev/null
+++ b/core/java/android/service/quickaccesswallet/GetWalletCardsResponse.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 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 android.service.quickaccesswallet;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The response for an {@link GetWalletCardsRequest} contains a list of wallet cards and the index
+ * of the card that should initially be displayed in the 'selected' position.
+ */
+public final class GetWalletCardsResponse implements Parcelable {
+
+    private final List<WalletCard> mWalletCards;
+    private final int mSelectedIndex;
+
+    /**
+     * Construct a new response.
+     *
+     * @param walletCards   The list of wallet cards.
+     * @param selectedIndex The index of the card that should be presented as the initially
+     *                      'selected' card
+     */
+    public GetWalletCardsResponse(@NonNull List<WalletCard> walletCards, int selectedIndex) {
+        this.mWalletCards = walletCards;
+        this.mSelectedIndex = selectedIndex;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(mWalletCards.size());
+        dest.writeParcelableList(mWalletCards, flags);
+        dest.writeInt(mSelectedIndex);
+    }
+
+    private static GetWalletCardsResponse readFromParcel(Parcel source) {
+        int size = source.readInt();
+        List<WalletCard> walletCards =
+                source.readParcelableList(new ArrayList<>(size), WalletCard.class.getClassLoader());
+        int selectedIndex = source.readInt();
+        return new GetWalletCardsResponse(walletCards, selectedIndex);
+    }
+
+    @NonNull
+    public static final Creator<GetWalletCardsResponse> CREATOR =
+            new Creator<GetWalletCardsResponse>() {
+                @Override
+                public GetWalletCardsResponse createFromParcel(Parcel source) {
+                    return readFromParcel(source);
+                }
+
+                @Override
+                public GetWalletCardsResponse[] newArray(int size) {
+                    return new GetWalletCardsResponse[size];
+                }
+            };
+
+    /**
+     * The list of {@link WalletCard}s. The size of this list should not exceed {@link
+     * GetWalletCardsRequest#getMaxCards()}.
+     */
+    @NonNull
+    public List<WalletCard> getWalletCards() {
+        return mWalletCards;
+    }
+
+    /**
+     * The {@code selectedIndex} represents the index of the card that should be presented in the
+     * 'selected' position when the cards are initially displayed in the quick access wallet.  The
+     * {@code selectedIndex} should be greater than or equal to zero and less than the size of the
+     * list of {@link WalletCard walletCards}, unless the list is empty in which case the {@code
+     * selectedIndex} can take any value. 0 is a nice round number for such cases.
+     */
+    public int getSelectedIndex() {
+        return mSelectedIndex;
+    }
+}
diff --git a/core/java/android/service/quickaccesswallet/IQuickAccessWalletService.aidl b/core/java/android/service/quickaccesswallet/IQuickAccessWalletService.aidl
new file mode 100644
index 0000000..ee70be4
--- /dev/null
+++ b/core/java/android/service/quickaccesswallet/IQuickAccessWalletService.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 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 android.service.quickaccesswallet;
+
+import android.service.quickaccesswallet.GetWalletCardsRequest;
+import android.service.quickaccesswallet.IQuickAccessWalletServiceCallbacks;
+import android.service.quickaccesswallet.SelectWalletCardRequest;
+import android.service.quickaccesswallet.WalletServiceEvent;
+import android.service.quickaccesswallet.WalletServiceEventListenerRequest;
+
+/**
+ * Implemented by QuickAccessWalletService in the payment application
+ *
+ * @hide
+ */
+interface IQuickAccessWalletService {
+    // Request to get cards, which should be provided using the callback.
+    oneway void onWalletCardsRequested(
+        in GetWalletCardsRequest request, in IQuickAccessWalletServiceCallbacks callback);
+    // Indicates that a card has been selected.
+    oneway void onWalletCardSelected(in SelectWalletCardRequest request);
+    // Sent when the wallet is dismissed or closed.
+    oneway void onWalletDismissed();
+    // Register an event listener
+    oneway void registerWalletServiceEventListener(
+        in WalletServiceEventListenerRequest request,
+        in IQuickAccessWalletServiceCallbacks callback);
+    // Unregister an event listener
+    oneway void unregisterWalletServiceEventListener(in WalletServiceEventListenerRequest request);
+}
\ No newline at end of file
diff --git a/core/java/android/service/quickaccesswallet/IQuickAccessWalletServiceCallbacks.aidl b/core/java/android/service/quickaccesswallet/IQuickAccessWalletServiceCallbacks.aidl
new file mode 100644
index 0000000..f37b930
--- /dev/null
+++ b/core/java/android/service/quickaccesswallet/IQuickAccessWalletServiceCallbacks.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright 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 android.service.quickaccesswallet;
+
+import android.service.quickaccesswallet.GetWalletCardsError;
+import android.service.quickaccesswallet.GetWalletCardsResponse;
+import android.service.quickaccesswallet.WalletServiceEvent;
+
+/**
+ * Interface to receive the result of requests to the wallet application.
+ *
+ * @hide
+ */
+interface IQuickAccessWalletServiceCallbacks {
+    // Called in response to onWalletCardsRequested on success. May only be called once per request.
+    oneway void onGetWalletCardsSuccess(in GetWalletCardsResponse response);
+    // Called in response to onWalletCardsRequested when an error occurs. May only be called once
+    // per request.
+    oneway void onGetWalletCardsFailure(in GetWalletCardsError error);
+    // Called in response to registerWalletServiceEventListener. May be called multiple times as
+    // long as the event listener is registered.
+    oneway void onWalletServiceEvent(in WalletServiceEvent event);
+}
\ No newline at end of file
diff --git a/core/java/android/service/quickaccesswallet/QuickAccessWalletClient.java b/core/java/android/service/quickaccesswallet/QuickAccessWalletClient.java
new file mode 100644
index 0000000..cfc6d57
--- /dev/null
+++ b/core/java/android/service/quickaccesswallet/QuickAccessWalletClient.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 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 android.service.quickaccesswallet;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.Intent;
+
+import java.util.function.Consumer;
+
+/**
+ * Facilitates accessing cards from the {@link QuickAccessWalletService}.
+ *
+ * @hide
+ */
+public interface QuickAccessWalletClient {
+
+    /**
+     * Create a client for accessing wallet cards from the {@link QuickAccessWalletService}. If the
+     * service is unavailable, {@link #isWalletServiceAvailable()} will return false.
+     */
+    @NonNull
+    static QuickAccessWalletClient create(@NonNull Context context) {
+        return new QuickAccessWalletClientImpl(context);
+    }
+
+    /**
+     * @return true if the {@link QuickAccessWalletService} is available.
+     */
+    boolean isWalletServiceAvailable();
+
+    /**
+     * Get wallet cards from the {@link QuickAccessWalletService}.
+     */
+    void getWalletCards(
+            @NonNull GetWalletCardsRequest request,
+            @NonNull Consumer<GetWalletCardsResponse> onSuccessListener,
+            @NonNull Consumer<GetWalletCardsError> onFailureListener);
+
+    /**
+     * Notify the {@link QuickAccessWalletService} service that a wallet card was selected.
+     */
+    void selectWalletCard(@NonNull SelectWalletCardRequest request);
+
+    /**
+     * Notify the {@link QuickAccessWalletService} service that the Wallet was dismissed.
+     */
+    void notifyWalletDismissed();
+
+    /**
+     * Unregister event listener.
+     */
+    void registerWalletServiceEventListener(Consumer<WalletServiceEvent> listener);
+
+    /**
+     * Unregister event listener
+     */
+    void unregisterWalletServiceEventListener(Consumer<WalletServiceEvent> listener);
+
+    /**
+     * The manifest entry for the QuickAccessWalletService may also publish information about the
+     * activity that hosts the Wallet view. This is typically the home screen of the Wallet
+     * application.
+     */
+    @Nullable
+    Intent getWalletActivity();
+
+    /**
+     * The manifest entry for the {@link QuickAccessWalletService} may publish the activity that
+     * hosts the settings
+     */
+    @Nullable
+    Intent getSettingsActivity();
+}
diff --git a/core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java b/core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java
new file mode 100644
index 0000000..17c287f
--- /dev/null
+++ b/core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java
@@ -0,0 +1,342 @@
+/*
+ * Copyright 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 android.service.quickaccesswallet;
+
+import static android.service.quickaccesswallet.QuickAccessWalletService.SERVICE_INTERFACE;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Queue;
+import java.util.UUID;
+import java.util.function.Consumer;
+
+/**
+ * @hide
+ */
+@SuppressWarnings("AndroidJdkLibsChecker")
+class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Handler.Callback,
+        ServiceConnection {
+
+    private static final String TAG = "QAWalletSClient";
+    private final Handler mHandler;
+    private final Context mContext;
+    private final Queue<ApiCaller> mRequestQueue;
+    private final Map<Consumer<WalletServiceEvent>, String> mEventListeners;
+    private boolean mIsConnected;
+    @Nullable
+    private IQuickAccessWalletService mService;
+
+
+    @Nullable
+    private final QuickAccessWalletServiceInfo mServiceInfo;
+
+    private static final int MSG_CONNECT = 1;
+    private static final int MSG_CONNECTED = 2;
+    private static final int MSG_EXECUTE = 3;
+    private static final int MSG_DISCONNECT = 4;
+
+    QuickAccessWalletClientImpl(@NonNull Context context) {
+        mContext = context.getApplicationContext();
+        mServiceInfo = QuickAccessWalletServiceInfo.tryCreate(context);
+        mHandler = new Handler(Looper.getMainLooper(), this);
+        mRequestQueue = new LinkedList<>();
+        mEventListeners = new HashMap<>(1);
+    }
+
+    @Override
+    public boolean handleMessage(Message msg) {
+        switch (msg.what) {
+            case MSG_CONNECT:
+                connectInternal();
+                break;
+            case MSG_CONNECTED:
+                onConnectedInternal((IQuickAccessWalletService) msg.obj);
+                break;
+            case MSG_EXECUTE:
+                executeInternal((ApiCaller) msg.obj);
+                break;
+            case MSG_DISCONNECT:
+                disconnectInternal();
+                break;
+            default:
+                Log.w(TAG, "Unknown what: " + msg.what);
+                return false;
+        }
+        return true;
+    }
+
+    private void connect() {
+        mHandler.sendMessage(mHandler.obtainMessage(MSG_CONNECT));
+    }
+
+    private void connectInternal() {
+        if (mServiceInfo == null) {
+            Log.w(TAG, "Wallet service unavailable");
+            return;
+        }
+        if (mIsConnected) {
+            Log.w(TAG, "already connected");
+            return;
+        }
+        mIsConnected = true;
+        Intent intent = new Intent(SERVICE_INTERFACE);
+        intent.setComponent(mServiceInfo.getComponentName());
+        int flags = Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY;
+        mContext.bindService(intent, this, flags);
+    }
+
+    private void onConnectedInternal(IQuickAccessWalletService service) {
+        if (!mIsConnected) {
+            Log.w(TAG, "onConnectInternal but connection closed");
+            mService = null;
+            return;
+        }
+        mService = service;
+        for (ApiCaller apiCaller : new ArrayList<>(mRequestQueue)) {
+            try {
+                apiCaller.performApiCall(mService);
+            } catch (RemoteException e) {
+                Log.e(TAG, "onConnectedInternal error", e);
+                apiCaller.onApiError();
+                disconnect();
+                break;
+            }
+            mRequestQueue.remove(apiCaller);
+        }
+    }
+
+    private void disconnect() {
+        mHandler.sendMessage(mHandler.obtainMessage(MSG_DISCONNECT));
+    }
+
+    private void disconnectInternal() {
+        if (!mIsConnected) {
+            Log.w(TAG, "already disconnected");
+            return;
+        }
+        mIsConnected = false;
+        mContext.unbindService(/*conn=*/this);
+        mService = null;
+        mEventListeners.clear();
+        mRequestQueue.clear();
+    }
+
+    private void execute(ApiCaller apiCaller) {
+        mHandler.sendMessage(mHandler.obtainMessage(MSG_EXECUTE, apiCaller));
+    }
+
+    private void executeInternal(ApiCaller apiCall) {
+        if (mIsConnected && mService != null) {
+            try {
+                apiCall.performApiCall(mService);
+            } catch (RemoteException e) {
+                Log.w(TAG, "executeInternal error", e);
+                apiCall.onApiError();
+                disconnect();
+            }
+        } else {
+            mRequestQueue.add(apiCall);
+            connect();
+        }
+    }
+
+    public boolean isWalletServiceAvailable() {
+        return mServiceInfo != null;
+    }
+
+    private abstract static class ApiCaller {
+        abstract void performApiCall(IQuickAccessWalletService service) throws RemoteException;
+
+        void onApiError() {
+            Log.w(TAG, "api error");
+        }
+    }
+
+    public void getWalletCards(
+            @NonNull GetWalletCardsRequest request,
+            @NonNull Consumer<GetWalletCardsResponse> onSuccessListener,
+            @NonNull Consumer<GetWalletCardsError> onFailureListener) {
+
+        BaseCallbacks callback = new BaseCallbacks() {
+            @Override
+            public void onGetWalletCardsSuccess(GetWalletCardsResponse response) {
+                mHandler.post(() -> onSuccessListener.accept(response));
+            }
+
+            @Override
+            public void onGetWalletCardsFailure(GetWalletCardsError error) {
+                mHandler.post(() -> onFailureListener.accept(error));
+            }
+        };
+
+        execute(new ApiCaller() {
+            @Override
+            public void performApiCall(IQuickAccessWalletService service) throws RemoteException {
+                service.onWalletCardsRequested(request, callback);
+            }
+
+            @Override
+            public void onApiError() {
+                callback.onGetWalletCardsFailure(new GetWalletCardsError(null, null));
+            }
+        });
+    }
+
+    public void selectWalletCard(@NonNull SelectWalletCardRequest request) {
+        execute(new ApiCaller() {
+            @Override
+            public void performApiCall(IQuickAccessWalletService service) throws RemoteException {
+                service.onWalletCardSelected(request);
+            }
+        });
+    }
+
+    public void notifyWalletDismissed() {
+        execute(new ApiCaller() {
+            @Override
+            public void performApiCall(IQuickAccessWalletService service) throws RemoteException {
+                service.onWalletDismissed();
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_DISCONNECT));
+            }
+        });
+    }
+
+    @Override
+    public void registerWalletServiceEventListener(Consumer<WalletServiceEvent> listener) {
+
+        BaseCallbacks callback = new BaseCallbacks() {
+            @Override
+            public void onWalletServiceEvent(WalletServiceEvent event) {
+                Log.i(TAG, "onWalletServiceEvent");
+                mHandler.post(() -> listener.accept(event));
+            }
+        };
+
+        execute(new ApiCaller() {
+            @Override
+            public void performApiCall(IQuickAccessWalletService service) throws RemoteException {
+                String listenerId = UUID.randomUUID().toString();
+                WalletServiceEventListenerRequest request =
+                        new WalletServiceEventListenerRequest(listenerId);
+                mEventListeners.put(listener, listenerId);
+                service.registerWalletServiceEventListener(request, callback);
+            }
+        });
+    }
+
+    @Override
+    public void unregisterWalletServiceEventListener(Consumer<WalletServiceEvent> listener) {
+        execute(new ApiCaller() {
+            @Override
+            public void performApiCall(IQuickAccessWalletService service) throws RemoteException {
+                String listenerId = mEventListeners.get(listener);
+                if (listenerId == null) {
+                    return;
+                }
+                WalletServiceEventListenerRequest request =
+                        new WalletServiceEventListenerRequest(listenerId);
+                service.unregisterWalletServiceEventListener(request);
+            }
+        });
+    }
+
+    @Override
+    @Nullable
+    public Intent getWalletActivity() {
+        if (mServiceInfo == null || TextUtils.isEmpty(mServiceInfo.getWalletActivity())) {
+            return null;
+        }
+        return new Intent(QuickAccessWalletService.ACTION_VIEW_WALLET)
+                .setComponent(
+                        new ComponentName(
+                                mServiceInfo.getComponentName().getPackageName(),
+                                mServiceInfo.getWalletActivity()));
+    }
+
+    @Override
+    @Nullable
+    public Intent getSettingsActivity() {
+        if (mServiceInfo == null || TextUtils.isEmpty(mServiceInfo.getSettingsActivity())) {
+            return null;
+        }
+        return new Intent(QuickAccessWalletService.ACTION_VIEW_WALLET_SETTINGS)
+                .setComponent(
+                        new ComponentName(
+                                mServiceInfo.getComponentName().getPackageName(),
+                                mServiceInfo.getSettingsActivity()));
+    }
+
+    /**
+     * Connection to the {@link QuickAccessWalletService}
+     */
+
+
+    @Override
+    public void onServiceConnected(ComponentName name, IBinder binder) {
+        IQuickAccessWalletService service = IQuickAccessWalletService.Stub.asInterface(binder);
+        mHandler.sendMessage(mHandler.obtainMessage(MSG_CONNECTED, service));
+    }
+
+    @Override
+    public void onServiceDisconnected(ComponentName name) {
+        // Do not disconnect, as we may later be re-connected
+        Log.w(TAG, "onServiceDisconnected");
+    }
+
+    @Override
+    public void onBindingDied(ComponentName name) {
+        // This is a recoverable error but the client will need to reconnect.
+        Log.w(TAG, "onBindingDied");
+        disconnect();
+    }
+
+    @Override
+    public void onNullBinding(ComponentName name) {
+        Log.w(TAG, "onNullBinding");
+        disconnect();
+    }
+
+    private static class BaseCallbacks extends IQuickAccessWalletServiceCallbacks.Stub {
+        public void onGetWalletCardsSuccess(GetWalletCardsResponse response) {
+            throw new IllegalStateException();
+        }
+
+        public void onGetWalletCardsFailure(GetWalletCardsError error) {
+            throw new IllegalStateException();
+        }
+
+        public void onWalletServiceEvent(WalletServiceEvent event) {
+            throw new IllegalStateException();
+        }
+    }
+}
diff --git a/core/java/android/service/quickaccesswallet/QuickAccessWalletService.java b/core/java/android/service/quickaccesswallet/QuickAccessWalletService.java
new file mode 100644
index 0000000..d968405
--- /dev/null
+++ b/core/java/android/service/quickaccesswallet/QuickAccessWalletService.java
@@ -0,0 +1,337 @@
+/*
+ * Copyright 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 android.service.quickaccesswallet;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SdkConstant;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Build;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.util.Log;
+
+/**
+ * A {@code QuickAccessWalletService} provides a list of {@code WalletCard}s shown in the Quick
+ * Access Wallet. The Quick Access Wallet allows the user to change their selected payment method
+ * and access other important passes, such as tickets and transit passes, without leaving the
+ * context of their current app.
+ *
+ * <p>An {@code QuickAccessWalletService} is only bound to the Android System for the purposes of
+ * showing wallet cards if:
+ * <ol>
+ *   <li>The application hosting the QuickAccessWalletService is also the default NFC payment
+ *   application. This means that the same application must also have a
+ *   {@link android.nfc.cardemulation.HostApduService} or
+ *   {@link android.nfc.cardemulation.OffHostApduService} that requires the
+ *   android.permission.BIND_NFC_SERVICE permission.
+ *   <li>The user explicitly selected the application as the default payment application in
+ *   the Tap &amp; pay settings screen.
+ *   <li>The application requires the {@code android.permission.BIND_QUICK_ACCESS_WALLET_SERVICE}
+ *   permission in its manifest.
+ *   <li>The user explicitly enables it using Android Settings (the
+ *       {@link Settings#ACTION_QUICK_ACCESS_WALLET_SETTINGS} intent can be used to launch it).
+ * </ol>
+ *
+ * <a name="BasicUsage"></a>
+ * <h3>Basic usage</h3>
+ *
+ * <p>The basic Quick Access Wallet process is defined by the workflow below:
+ * <ol>
+ *   <li>User performs a gesture to bring up the Quick Access Wallet, which is displayed by the
+ *   Android System.
+ *   <li>The Android System creates a {@link GetWalletCardsRequest}, binds to the
+ *   {@link QuickAccessWalletService}, and delivers the request.
+ *   <li>The service receives the request through {@link #onWalletCardsRequested}
+ *   <li>The service responds by calling {@link GetWalletCardsCallback#onSuccess} with a
+ *   {@link GetWalletCardsResponse response} that contains between 1 and
+ *   {@link GetWalletCardsRequest#getMaxCards() maxCards} cards.
+ *   <li>The Android System displays the Quick Access Wallet containing the provided cards. The
+ *   card at the {@link GetWalletCardsResponse#getSelectedIndex() selectedIndex} will initially
+ *   be presented as the 'selected' card.
+ *   <li>As soon as the cards are displayed, the Android System will notify the service that the
+ *   card at the selected index has been selected through {@link #onWalletCardSelected}.
+ *   <li>The user interacts with the wallet and may select one or more cards in sequence. Each time
+ *   a new card is selected, the Android System will notify the service through
+ *   {@link #onWalletCardSelected} and will provide the {@link WalletCard#getCardId() cardId} of the
+ *   card that is now selected.
+ *   <li>When the wallet is dismissed, the Android System will notify the service through
+ *   {@link #onWalletDismissed}.
+ * </ol>
+ *
+ * <p>The workflow is designed to minimize the time that the Android System is bound to the
+ * service, but connections may be cached and reused to improve performance and conserve memory.
+ * All calls should be considered stateless: if the service needs to keep state between calls, it
+ * must do its own state management (keeping in mind that the service's process might be killed
+ * by the Android System when unbound; for example, if the device is running low in memory).
+ *
+ * <p>
+ * <a name="ErrorHandling"></a>
+ * <h3>Error handling</h3>
+ * <p>If the service encountered an error processing the request, it should call
+ * {@link GetWalletCardsCallback#onFailure}.
+ * For performance reasons, it's paramount that the service calls either
+ * {@link GetWalletCardsCallback#onSuccess} or
+ * {@link GetWalletCardsCallback#onFailure} for each
+ * {@link #onWalletCardsRequested} received - if it doesn't, the request will eventually time out
+ * and be discarded by the Android System.
+ *
+ * <p>
+ * <a name="ManifestEntry"></a>
+ * <h3>Manifest entry</h3>
+ *
+ * <p>QuickAccessWalletService must require the permission
+ * "android.permission.BIND_QUICK_ACCESS_WALLET_SERVICE".
+ *
+ * <pre class="prettyprint">
+ * {@literal
+ * <service
+ *     android:name=".MyQuickAccessWalletService"
+ *     android:label="@string/my_default_tile_label"
+ *     android:icon="@drawable/my_default_icon_label"
+ *     android:permission="android.permission.BIND_QUICK_ACCESS_WALLET_SERVICE">
+ *     <intent-filter>
+ *         <action android:name="android.service.quickaccesswallet.QuickAccessWalletService" />
+ *     </intent-filter>
+ *     <meta-data android:name="android.quickaccesswallet"
+ *          android:resource="@xml/quickaccesswallet_configuration" />;
+ * </service>}
+ * </pre>
+ * <p>
+ * The {@literal <meta-data>} element includes an android:resource attribute that points to an
+ * XML resource with further details about the service. The {@code quickaccesswallet_configuration}
+ * in the example above specifies an activity that allows the users to view the entire wallet.
+ * The following example shows the quickaccesswallet_configuration XML resource:
+ * <p>
+ * <pre class="prettyprint">
+ * {@literal
+ * <quickaccesswallet-service
+ *   xmlns:android="http://schemas.android.com/apk/res/android"
+ *   android:settingsActivity="com.example.android.SettingsActivity"
+ *   android:targetActivity="com.example.android.WalletActivity"/>
+ * }
+ * </pre>
+ *
+ * <p>The entry for {@code settingsActivity} should contain the fully qualified class name of an
+ * activity that allows the user to modify the settings for this service. The {@code targetActivity}
+ * entry should contain the fully qualified class name of an activity that allows the user to view
+ * their entire wallet. If specified, the wallet activity will be started with the Intent action
+ * {@link #ACTION_VIEW_WALLET} and the settings activity will be started with the Intent action
+ * {@link #ACTION_VIEW_WALLET_SETTINGS}.
+ */
+public abstract class QuickAccessWalletService extends Service {
+
+    private static final String TAG = "QAWalletService";
+
+    /**
+     * The {@link Intent} that must be declared as handled by the service. To be supported, the
+     * service must also require the
+     * {@link android.Manifest.permission#BIND_QUICK_ACCESS_WALLET_SERVICE}
+     * permission so that other applications can not abuse it.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+    public static final String SERVICE_INTERFACE =
+            "android.service.quickaccesswallet.QuickAccessWalletService";
+
+    /**
+     * Intent action to launch an activity to display the wallet.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_VIEW_WALLET =
+            "android.service.quickaccesswallet.action.VIEW_WALLET";
+
+    /**
+     * Intent action to launch an activity to display quick access wallet settings.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_VIEW_WALLET_SETTINGS =
+            "android.service.quickaccesswallet.action.VIEW_WALLET_SETTINGS";
+
+    /**
+     * Broadcast Action: Sent by the wallet application to dismiss the Quick Access Wallet.
+     * <p>
+     * The Quick Access Wallet may be shown in a system window on top of other Activities. If the
+     * user selects a payment card from the Quick Access Wallet and then holds their phone to an NFC
+     * terminal, the wallet application will need to show a payment Activity. But if the Quick
+     * Access Wallet is still being shown, it may obscure the payment Activity. To avoid this, the
+     * wallet application can send a broadcast to the Android System with this action to request
+     * that the Quick Access Wallet be dismissed.
+     * <p>
+     * This broadcast must use the {@code android.permission.BIND_QUICK_ACCESS_WALLET_SERVICE}
+     * permission to ensure that it is only delivered to System UI. Furthermore, your application
+     * must require the {@code android.permission.DISMISS_QUICK_ACCESS_WALLET}
+     * <p>
+     * <pre class="prettyprint">
+     * context.sendBroadcast(
+     *     new Intent(ACTION_DISMISS_WALLET), Manifest.permission.BIND_QUICK_ACCESS_WALLET_SERVICE);
+     * </pre>
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_DISMISS_WALLET =
+            "android.service.quickaccesswallet.action.DISMISS_WALLET";
+
+    /**
+     * Name under which a QuickAccessWalletService component publishes information about itself.
+     * This meta-data should reference an XML resource containing a
+     * <code>&lt;{@link
+     * android.R.styleable#QuickAccessWalletService quickaccesswallet-service}&gt;</code> tag. This
+     * is a a sample XML file configuring an QuickAccessWalletService:
+     * <pre> &lt;quickaccesswallet-service
+     *     android:walletActivity="foo.bar.WalletActivity"
+     *     . . .
+     * /&gt;</pre>
+     */
+    public static final String SERVICE_META_DATA = "android.quickaccesswallet";
+
+    private final Handler mHandler = new Handler(Looper.getMainLooper());
+    @Nullable
+    private String mEventListenerId;
+    @Nullable
+    private IQuickAccessWalletServiceCallbacks mEventListener;
+
+    private final IQuickAccessWalletService mInterface = new IQuickAccessWalletService.Stub() {
+        @Override
+        public void onWalletCardsRequested(
+                @NonNull GetWalletCardsRequest request,
+                @NonNull IQuickAccessWalletServiceCallbacks callback) {
+            mHandler.post(() -> onWalletCardsRequestedInternal(request, callback));
+        }
+
+        @Override
+        public void onWalletCardSelected(@NonNull SelectWalletCardRequest request) {
+            mHandler.post(() -> QuickAccessWalletService.this.onWalletCardSelected(request));
+        }
+
+        @Override
+        public void onWalletDismissed() {
+            mHandler.post(QuickAccessWalletService.this::onWalletDismissed);
+        }
+
+        public void registerWalletServiceEventListener(
+                @NonNull WalletServiceEventListenerRequest request,
+                @NonNull IQuickAccessWalletServiceCallbacks callback) {
+            mHandler.post(() -> registerDismissWalletListenerInternal(request, callback));
+        }
+
+        public void unregisterWalletServiceEventListener(
+                @NonNull WalletServiceEventListenerRequest request) {
+            mHandler.post(() -> unregisterDismissWalletListenerInternal(request));
+        }
+    };
+
+    private void onWalletCardsRequestedInternal(
+            GetWalletCardsRequest request,
+            IQuickAccessWalletServiceCallbacks callback) {
+        onWalletCardsRequested(request, new GetWalletCardsCallback(callback, mHandler));
+    }
+
+    @Override
+    @Nullable
+    public IBinder onBind(@NonNull Intent intent) {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
+            // Binding to the QuickAccessWalletService is protected by the
+            // android.permission.BIND_QUICK_ACCESS_WALLET_SERVICE permission, which is defined in
+            // R. Pre-R devices can have other side-loaded applications that claim this permission.
+            // This ensures that the service is only available when properly permission protected.
+            Log.w(TAG, "Warning: binding on pre-R device");
+        }
+        if (SERVICE_INTERFACE.equals(intent.getAction())) {
+            return mInterface.asBinder();
+        }
+        Log.w(TAG, "Tried to bind to wrong intent (should be " + SERVICE_INTERFACE + ": " + intent);
+        return null;
+    }
+
+    /**
+     * Called when the user requests the service to provide wallet cards.
+     *
+     * <p>This method will be called on the main thread, but the callback may be called from any
+     * thread. The callback should be called as quickly as possible. The service must always call
+     * either {@link GetWalletCardsCallback#onSuccess(GetWalletCardsResponse)} or {@link
+     * GetWalletCardsCallback#onFailure(GetWalletCardsError)}. Calling multiple times or calling
+     * both methods will cause an exception to be thrown.
+     */
+    public abstract void onWalletCardsRequested(
+            @NonNull GetWalletCardsRequest request,
+            @NonNull GetWalletCardsCallback callback);
+
+    /**
+     * A wallet card was selected. Sent when the user selects a wallet card from the list of cards.
+     * Selection may indicate that the card is now in the center of the screen, or highlighted in
+     * some other fashion. It does not mean that the user clicked on the card -- clicking on the
+     * card will cause the {@link WalletCard#getPendingIntent()} to be sent.
+     *
+     * <p>Card selection events are especially important to NFC payment applications because
+     * many NFC terminals can only accept one payment card at a time. If the user has several NFC
+     * cards in their wallet, selecting different cards can change which payment method is presented
+     * to the terminal.
+     */
+    public abstract void onWalletCardSelected(@NonNull SelectWalletCardRequest request);
+
+    /**
+     * Indicates that the wallet was dismissed. This is received when the Quick Access Wallet is no
+     * longer visible.
+     */
+    public abstract void onWalletDismissed();
+
+    /**
+     * Send a {@link WalletServiceEvent} to the Quick Access Wallet.
+     * <p>
+     * Background events may require that the Quick Access Wallet view be updated. For example, if
+     * the wallet application hosting this service starts to handle an NFC payment while the Quick
+     * Access Wallet is being shown, the Quick Access Wallet will need to be dismissed so that the
+     * Activity showing the payment can be displayed to the user.
+     */
+    public final void sendWalletServiceEvent(@NonNull WalletServiceEvent serviceEvent) {
+        mHandler.post(() -> sendWalletServiceEventInternal(serviceEvent));
+    }
+
+    private void sendWalletServiceEventInternal(WalletServiceEvent serviceEvent) {
+        if (mEventListener == null) {
+            Log.i(TAG, "No dismiss listener registered");
+            return;
+        }
+        try {
+            mEventListener.onWalletServiceEvent(serviceEvent);
+        } catch (RemoteException e) {
+            Log.w(TAG, "onWalletServiceEvent error", e);
+            mEventListenerId = null;
+            mEventListener = null;
+        }
+    }
+
+    private void registerDismissWalletListenerInternal(
+            @NonNull WalletServiceEventListenerRequest request,
+            @NonNull IQuickAccessWalletServiceCallbacks callback) {
+        mEventListenerId = request.getListenerId();
+        mEventListener = callback;
+    }
+
+    private void unregisterDismissWalletListenerInternal(
+            @NonNull WalletServiceEventListenerRequest request) {
+        if (mEventListenerId != null && mEventListenerId.equals(request.getListenerId())) {
+            mEventListenerId = null;
+            mEventListener = null;
+        } else {
+            Log.w(TAG, "dismiss listener missing or replaced");
+        }
+    }
+}
diff --git a/core/java/android/service/quickaccesswallet/QuickAccessWalletServiceInfo.java b/core/java/android/service/quickaccesswallet/QuickAccessWalletServiceInfo.java
new file mode 100644
index 0000000..8793f28
--- /dev/null
+++ b/core/java/android/service/quickaccesswallet/QuickAccessWalletServiceInfo.java
@@ -0,0 +1,187 @@
+/*
+ * 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 android.service.quickaccesswallet;
+
+import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.provider.Settings;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Xml;
+
+import com.android.internal.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * {@link ServiceInfo} and meta-data about a {@link QuickAccessWalletService}.
+ *
+ * @hide
+ */
+class QuickAccessWalletServiceInfo {
+
+    private static final String TAG = "QAWalletSInfo";
+    private static final String TAG_WALLET_SERVICE = "quickaccesswallet-service";
+
+    private final ServiceInfo mServiceInfo;
+    private final ServiceMetadata mServiceMetadata;
+
+    private QuickAccessWalletServiceInfo(
+            @NonNull ServiceInfo serviceInfo,
+            @NonNull ServiceMetadata metadata) {
+        mServiceInfo = serviceInfo;
+        mServiceMetadata = metadata;
+    }
+
+    @Nullable
+    static QuickAccessWalletServiceInfo tryCreate(@NonNull Context context) {
+        ComponentName defaultPaymentApp = getDefaultPaymentApp(context);
+        if (defaultPaymentApp == null) {
+            Log.d(TAG, "create: default payment app not set");
+            return null;
+        }
+
+        ServiceInfo serviceInfo = getWalletServiceInfo(context, defaultPaymentApp.getPackageName());
+        if (serviceInfo == null) {
+            Log.d(TAG, "create: unable to resolve service intent");
+            return null;
+        }
+
+        if (!Manifest.permission.BIND_QUICK_ACCESS_WALLET_SERVICE.equals(serviceInfo.permission)) {
+            Log.w(TAG, String.format("QuickAccessWalletService from %s does not have permission %s",
+                    serviceInfo.packageName, Manifest.permission.BIND_QUICK_ACCESS_WALLET_SERVICE));
+            return null;
+        }
+
+        ServiceMetadata metadata = parseServiceMetadata(context, serviceInfo);
+        return new QuickAccessWalletServiceInfo(serviceInfo, metadata);
+    }
+
+    private static ComponentName getDefaultPaymentApp(Context context) {
+        ContentResolver cr = context.getContentResolver();
+        String comp = Settings.Secure.getString(cr, Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT);
+        return comp == null ? null : ComponentName.unflattenFromString(comp);
+    }
+
+    private static ServiceInfo getWalletServiceInfo(Context context, String packageName) {
+        Intent intent = new Intent(QuickAccessWalletService.SERVICE_INTERFACE);
+        intent.setPackage(packageName);
+        List<ResolveInfo> resolveInfos =
+                context.getPackageManager().queryIntentServices(intent,
+                        PackageManager.MATCH_DEFAULT_ONLY);
+        return resolveInfos.isEmpty() ? null : resolveInfos.get(0).serviceInfo;
+    }
+
+    private static class ServiceMetadata {
+        @Nullable
+        private final String mSettingsActivity;
+        @Nullable
+        private final String mWalletActivity;
+
+        private ServiceMetadata(String settingsActivity, String walletActivity) {
+            this.mSettingsActivity = settingsActivity;
+            this.mWalletActivity = walletActivity;
+        }
+    }
+
+    private static ServiceMetadata parseServiceMetadata(Context context, ServiceInfo serviceInfo) {
+        PackageManager pm = context.getPackageManager();
+        final XmlResourceParser parser =
+                serviceInfo.loadXmlMetaData(pm, QuickAccessWalletService.SERVICE_META_DATA);
+
+        if (parser == null) {
+            return new ServiceMetadata(null, null);
+        }
+
+        try {
+            Resources resources = pm.getResourcesForApplication(serviceInfo.applicationInfo);
+            int type = 0;
+            while (type != XmlPullParser.END_DOCUMENT && type != XmlPullParser.START_TAG) {
+                type = parser.next();
+            }
+
+            if (TAG_WALLET_SERVICE.equals(parser.getName())) {
+                final AttributeSet allAttributes = Xml.asAttributeSet(parser);
+                TypedArray afsAttributes = null;
+                try {
+                    afsAttributes = resources.obtainAttributes(allAttributes,
+                            R.styleable.QuickAccessWalletService);
+                    String settingsActivity = afsAttributes.getString(
+                            R.styleable.QuickAccessWalletService_settingsActivity);
+                    String walletActivity = afsAttributes.getString(
+                            R.styleable.QuickAccessWalletService_targetActivity);
+                    return new ServiceMetadata(settingsActivity, walletActivity);
+                } finally {
+                    if (afsAttributes != null) {
+                        afsAttributes.recycle();
+                    }
+                }
+            } else {
+                Log.e(TAG, "Meta-data does not start with quickaccesswallet-service tag");
+            }
+
+        } catch (PackageManager.NameNotFoundException
+                | IOException
+                | XmlPullParserException e) {
+            Log.e(TAG, "Error parsing quickaccesswallet service meta-data", e);
+        }
+        return new ServiceMetadata(null, null);
+    }
+
+    /**
+     * @return the component name of the {@link QuickAccessWalletService}
+     */
+    @NonNull
+    ComponentName getComponentName() {
+        return mServiceInfo.getComponentName();
+    }
+
+    /**
+     * @return the fully qualified name of the activity that hosts the full wallet. If available,
+     * this intent should be started with the action
+     * {@link QuickAccessWalletService#ACTION_VIEW_WALLET}
+     */
+    @Nullable
+    String getWalletActivity() {
+        return mServiceMetadata.mWalletActivity;
+    }
+
+    /**
+     * @return the fully qualified name of the activity that allows the user to change quick access
+     * wallet settings. If available, this intent should be started with the action {@link
+     * QuickAccessWalletService#ACTION_VIEW_WALLET_SETTINGS}
+     */
+    @Nullable
+    String getSettingsActivity() {
+        return mServiceMetadata.mSettingsActivity;
+    }
+}
diff --git a/core/java/android/service/quickaccesswallet/SelectWalletCardRequest.aidl b/core/java/android/service/quickaccesswallet/SelectWalletCardRequest.aidl
new file mode 100644
index 0000000..97a0d41
--- /dev/null
+++ b/core/java/android/service/quickaccesswallet/SelectWalletCardRequest.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 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 android.service.quickaccesswallet;
+
+parcelable SelectWalletCardRequest;
\ No newline at end of file
diff --git a/core/java/android/service/quickaccesswallet/SelectWalletCardRequest.java b/core/java/android/service/quickaccesswallet/SelectWalletCardRequest.java
new file mode 100644
index 0000000..cb69eee
--- /dev/null
+++ b/core/java/android/service/quickaccesswallet/SelectWalletCardRequest.java
@@ -0,0 +1,74 @@
+/*
+ * 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 android.service.quickaccesswallet;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Represents a request to a {@link QuickAccessWalletService} to select a particular {@link
+ * WalletCard walletCard}. Card selection events are transmitted to the WalletService so that the
+ * selected card may be used by the NFC payment service.
+ */
+public final class SelectWalletCardRequest implements Parcelable {
+
+    private final String mCardId;
+
+    /**
+     * Creates a new GetWalletCardsRequest.
+     *
+     * @param cardId The {@link WalletCard#getCardId() cardId} of the wallet card that is currently
+     *               selected.
+     */
+    public SelectWalletCardRequest(@NonNull String cardId) {
+        this.mCardId = cardId;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeString(mCardId);
+    }
+
+    @NonNull
+    public static final Creator<SelectWalletCardRequest> CREATOR =
+            new Creator<SelectWalletCardRequest>() {
+                @Override
+                public SelectWalletCardRequest createFromParcel(Parcel source) {
+                    String cardId = source.readString();
+                    return new SelectWalletCardRequest(cardId);
+                }
+
+                @Override
+                public SelectWalletCardRequest[] newArray(int size) {
+                    return new SelectWalletCardRequest[size];
+                }
+            };
+
+    /**
+     * The {@link WalletCard#getCardId() cardId} of the wallet card that is currently selected.
+     */
+    @NonNull
+    public String getCardId() {
+        return mCardId;
+    }
+}
diff --git a/core/java/android/service/quickaccesswallet/WalletCard.aidl b/core/java/android/service/quickaccesswallet/WalletCard.aidl
new file mode 100644
index 0000000..115213d
--- /dev/null
+++ b/core/java/android/service/quickaccesswallet/WalletCard.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 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 android.service.quickaccesswallet;
+
+parcelable WalletCard;
\ No newline at end of file
diff --git a/core/java/android/service/quickaccesswallet/WalletCard.java b/core/java/android/service/quickaccesswallet/WalletCard.java
new file mode 100644
index 0000000..c3b1a4b
--- /dev/null
+++ b/core/java/android/service/quickaccesswallet/WalletCard.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright 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 android.service.quickaccesswallet;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.PendingIntent;
+import android.graphics.drawable.Icon;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+/**
+ * A {@link WalletCard} can represent anything that a user might carry in their wallet -- a credit
+ * card, library card, transit pass, etc. Cards are identified by a String identifier and contain a
+ * card image, card image content description, and a {@link PendingIntent} to be used if the user
+ * clicks on the card. Cards may be displayed with an icon and label, though these are optional.
+ */
+public final class WalletCard implements Parcelable {
+
+    private final String mCardId;
+    private final Icon mCardImage;
+    private final CharSequence mContentDescription;
+    private final PendingIntent mPendingIntent;
+    private final Icon mCardIcon;
+    private final CharSequence mCardLabel;
+
+    private WalletCard(Builder builder) {
+        this.mCardId = builder.mCardId;
+        this.mCardImage = builder.mCardImage;
+        this.mContentDescription = builder.mContentDescription;
+        this.mPendingIntent = builder.mPendingIntent;
+        this.mCardIcon = builder.mCardIcon;
+        this.mCardLabel = builder.mCardLabel;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeString(mCardId);
+        mCardImage.writeToParcel(dest, flags);
+        TextUtils.writeToParcel(mContentDescription, dest, flags);
+        PendingIntent.writePendingIntentOrNullToParcel(mPendingIntent, dest);
+        if (mCardIcon == null) {
+            dest.writeByte((byte) 0);
+        } else {
+            dest.writeByte((byte) 1);
+            mCardIcon.writeToParcel(dest, flags);
+        }
+        TextUtils.writeToParcel(mCardLabel, dest, flags);
+    }
+
+    private static WalletCard readFromParcel(Parcel source) {
+        String cardId = source.readString();
+        Icon cardImage = Icon.CREATOR.createFromParcel(source);
+        CharSequence contentDesc = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
+        PendingIntent pendingIntent = PendingIntent.readPendingIntentOrNullFromParcel(source);
+        Icon cardIcon = source.readByte() == 0 ? null : Icon.CREATOR.createFromParcel(source);
+        CharSequence cardLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
+        return new Builder(cardId, cardImage, contentDesc, pendingIntent)
+                .setCardIcon(cardIcon)
+                .setCardLabel(cardLabel)
+                .build();
+    }
+
+    @NonNull
+    public static final Creator<WalletCard> CREATOR =
+            new Creator<WalletCard>() {
+                @Override
+                public WalletCard createFromParcel(Parcel source) {
+                    return readFromParcel(source);
+                }
+
+                @Override
+                public WalletCard[] newArray(int size) {
+                    return new WalletCard[size];
+                }
+            };
+
+    /**
+     * The card id must be unique within the list of cards returned.
+     */
+    @NonNull
+    public String getCardId() {
+        return mCardId;
+    }
+
+    /**
+     * The visual representation of the card. If the card image Icon is a bitmap, it should have a
+     * width of {@link GetWalletCardsRequest#getCardWidthPx()} and a height of {@link
+     * GetWalletCardsRequest#getCardHeightPx()}.
+     */
+    @NonNull
+    public Icon getCardImage() {
+        return mCardImage;
+    }
+
+    /**
+     * The content description of the card image.
+     */
+    @NonNull
+    public CharSequence getContentDescription() {
+        return mContentDescription;
+    }
+
+    /**
+     * If the user performs a click on the card, this PendingIntent will be sent. If the device is
+     * locked, the wallet will first request device unlock before sending the pending intent.
+     */
+    @NonNull
+    public PendingIntent getPendingIntent() {
+        return mPendingIntent;
+    }
+
+    /**
+     * An icon may be shown alongside the card image to convey information about how the card can be
+     * used, or if some other action must be taken before using the card. For example, an NFC logo
+     * could indicate that the card is NFC-enabled and will be provided to an NFC terminal if the
+     * phone is held in close proximity to the NFC reader.
+     *
+     * <p>If the supplied Icon is backed by a bitmap, it should have width and height
+     * {@link GetWalletCardsRequest#getIconSizePx()}.
+     */
+    @Nullable
+    public Icon getCardIcon() {
+        return mCardIcon;
+    }
+
+    /**
+     * A card label may be shown alongside the card image to convey information about how the card
+     * can be used, or if some other action must be taken before using the card. For example, an
+     * NFC-enabled card could be labeled "Hold near reader" to inform the user of how to use NFC
+     * cards when interacting with an NFC reader.
+     *
+     * <p>If the provided label is too long to fit on one line, it may be truncated and ellipsized.
+     */
+    @Nullable
+    public CharSequence getCardLabel() {
+        return mCardLabel;
+    }
+
+    /**
+     * Builder for {@link WalletCard} objects. You must to provide cardId, cardImage,
+     * contentDescription, and pendingIntent. If the card is opaque and should be shown with
+     * elevation, set hasShadow to true. cardIcon and cardLabel are optional.
+     */
+    public static final class Builder {
+        private String mCardId;
+        private Icon mCardImage;
+        private CharSequence mContentDescription;
+        private PendingIntent mPendingIntent;
+        private Icon mCardIcon;
+        private CharSequence mCardLabel;
+
+        /**
+         * @param cardId             The card id must be non-null and unique within the list of
+         *                           cards returned. <b>Note:
+         *                           </b> this card ID should <b>not</b> contain PII (Personally
+         *                           Identifiable Information, * such as username or email
+         *                           address).
+         * @param cardImage          The visual representation of the card. If the card image Icon
+         *                           is a bitmap, it should have a width of {@link
+         *                           GetWalletCardsRequest#getCardWidthPx()} and a height of {@link
+         *                           GetWalletCardsRequest#getCardHeightPx()}. If the card image
+         *                           does not have these dimensions, it may appear distorted when it
+         *                           is scaled to fit these dimensions on screen.
+         * @param contentDescription The content description of the card image. This field is
+         *                           required.
+         *                           <b>Note: </b> this message should <b>not</b> contain PII
+         *                           (Personally Identifiable Information, such as username or email
+         *                           address).
+         * @param pendingIntent      If the user performs a click on the card, this PendingIntent
+         *                           will be sent. If the device is locked, the wallet will first
+         *                           request device unlock before sending the pending intent.
+         */
+        public Builder(@NonNull String cardId,
+                @NonNull Icon cardImage,
+                @NonNull CharSequence contentDescription,
+                @NonNull PendingIntent pendingIntent) {
+            mCardId = cardId;
+            mCardImage = cardImage;
+            mContentDescription = contentDescription;
+            mPendingIntent = pendingIntent;
+        }
+
+        /**
+         * An icon may be shown alongside the card image to convey information about how the card
+         * can be used, or if some other action must be taken before using the card. For example, an
+         * NFC logo could indicate that the card is NFC-enabled and will be provided to an NFC
+         * terminal if the phone is held in close proximity to the NFC reader. This field is
+         * optional.
+         *
+         * <p>If the supplied Icon is backed by a bitmap, it should have width and height
+         * {@link GetWalletCardsRequest#getIconSizePx()}.
+         */
+        @NonNull
+        public Builder setCardIcon(@Nullable Icon cardIcon) {
+            mCardIcon = cardIcon;
+            return this;
+        }
+
+        /**
+         * A card label may be shown alongside the card image to convey information about how the
+         * card can be used, or if some other action must be taken before using the card. For
+         * example, an NFC-enabled card could be labeled "Hold near reader" to inform the user of
+         * how to use NFC cards when interacting with an NFC reader. This field is optional.
+         * <b>Note: </b> this card label should <b>not</b> contain PII (Personally Identifiable
+         * Information, such as username or email address). If the provided label is too long to fit
+         * on one line, it may be truncated and ellipsized.
+         */
+        @NonNull
+        public Builder setCardLabel(@Nullable CharSequence cardLabel) {
+            mCardLabel = cardLabel;
+            return this;
+        }
+
+        /**
+         * Builds a new {@link WalletCard} instance.
+         *
+         * @return A built response.
+         */
+        @NonNull
+        public WalletCard build() {
+            return new WalletCard(this);
+        }
+    }
+}
diff --git a/core/java/android/service/quickaccesswallet/WalletServiceEvent.aidl b/core/java/android/service/quickaccesswallet/WalletServiceEvent.aidl
new file mode 100644
index 0000000..891cf1d
--- /dev/null
+++ b/core/java/android/service/quickaccesswallet/WalletServiceEvent.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 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 android.service.quickaccesswallet;
+
+parcelable WalletServiceEvent;
\ No newline at end of file
diff --git a/core/java/android/service/quickaccesswallet/WalletServiceEvent.java b/core/java/android/service/quickaccesswallet/WalletServiceEvent.java
new file mode 100644
index 0000000..fb524be
--- /dev/null
+++ b/core/java/android/service/quickaccesswallet/WalletServiceEvent.java
@@ -0,0 +1,92 @@
+/*
+ * 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 android.service.quickaccesswallet;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Represents a request from the {@link QuickAccessWalletService wallet app} to the Quick Access
+ * Wallet in System UI. Background events may necessitate that the Quick Access Wallet update its
+ * view. For example, if the wallet application handles an NFC payment while the Quick Access Wallet
+ * is being shown, it needs to tell the Quick Access Wallet so that the wallet can be dismissed and
+ * Activity showing the payment can be displayed to the user.
+ */
+public final class WalletServiceEvent implements Parcelable {
+
+    /**
+     * An NFC payment has started. If the Quick Access Wallet is in a system window, it will need to
+     * be dismissed so that an Activity showing the payment can be displayed.
+     */
+    public static final int TYPE_NFC_PAYMENT_STARTED = 1;
+
+    /**
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({TYPE_NFC_PAYMENT_STARTED})
+    public @interface EventType {
+    }
+
+    @EventType
+    private final int mEventType;
+
+    /**
+     * Creates a new DismissWalletRequest.
+     */
+    public WalletServiceEvent(@EventType int eventType) {
+        this.mEventType = eventType;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(mEventType);
+    }
+
+    @NonNull
+    public static final Creator<WalletServiceEvent> CREATOR =
+            new Creator<WalletServiceEvent>() {
+                @Override
+                public WalletServiceEvent createFromParcel(Parcel source) {
+                    int eventType = source.readInt();
+                    return new WalletServiceEvent(eventType);
+                }
+
+                @Override
+                public WalletServiceEvent[] newArray(int size) {
+                    return new WalletServiceEvent[size];
+                }
+            };
+
+    /**
+     * @return the event type
+     */
+    @EventType
+    public int getEventType() {
+        return mEventType;
+    }
+}
diff --git a/core/java/android/service/quickaccesswallet/WalletServiceEventListenerRequest.aidl b/core/java/android/service/quickaccesswallet/WalletServiceEventListenerRequest.aidl
new file mode 100644
index 0000000..155f92e
--- /dev/null
+++ b/core/java/android/service/quickaccesswallet/WalletServiceEventListenerRequest.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 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 android.service.quickaccesswallet;
+
+parcelable WalletServiceEventListenerRequest;
\ No newline at end of file
diff --git a/core/java/android/service/quickaccesswallet/WalletServiceEventListenerRequest.java b/core/java/android/service/quickaccesswallet/WalletServiceEventListenerRequest.java
new file mode 100644
index 0000000..223110e
--- /dev/null
+++ b/core/java/android/service/quickaccesswallet/WalletServiceEventListenerRequest.java
@@ -0,0 +1,78 @@
+/*
+ * 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 android.service.quickaccesswallet;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Register a dismiss request listener with the QuickAccessWalletService. This allows the service to
+ * dismiss the wallet if it needs to show a payment activity in response to an NFC event.
+ *
+ * @hide
+ */
+public final class WalletServiceEventListenerRequest implements Parcelable {
+
+    private final String mListenerId;
+
+    /**
+     * Construct a new {@code DismissWalletListenerRequest}.
+     *
+     * @param listenerKey A unique key that identifies the listener.
+     */
+    public WalletServiceEventListenerRequest(@NonNull String listenerKey) {
+        mListenerId = listenerKey;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeString(mListenerId);
+    }
+
+    private static WalletServiceEventListenerRequest readFromParcel(Parcel source) {
+        String listenerId = source.readString();
+        return new WalletServiceEventListenerRequest(listenerId);
+    }
+
+    @NonNull
+    public static final Creator<WalletServiceEventListenerRequest> CREATOR =
+            new Creator<WalletServiceEventListenerRequest>() {
+                @Override
+                public WalletServiceEventListenerRequest createFromParcel(Parcel source) {
+                    return readFromParcel(source);
+                }
+
+                @Override
+                public WalletServiceEventListenerRequest[] newArray(int size) {
+                    return new WalletServiceEventListenerRequest[size];
+                }
+            };
+
+    /**
+     * Returns the unique key that identifies the wallet dismiss request listener.
+     */
+    @NonNull
+    public String getListenerId() {
+        return mListenerId;
+    }
+}
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index 4def80e..67cac0e 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -188,6 +188,10 @@
      * Listen for {@link android.telephony.Annotation.PreciseCallStates} of ringing,
      * background and foreground calls.
      *
+     * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
+     * or the calling app has carrier privileges
+     * (see {@link TelephonyManager#hasCarrierPrivileges}).
+     *
      * @hide
      */
     @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
@@ -197,13 +201,13 @@
     /**
      * Listen for {@link PreciseDataConnectionState} on the data connection (cellular).
      *
-     * <p>Requires permission {@link android.Manifest.permission#MODIFY_PHONE_STATE}
+     * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
      * or the calling app has carrier privileges
      * (see {@link TelephonyManager#hasCarrierPrivileges}).
      *
      * @see #onPreciseDataConnectionStateChanged
      */
-    @RequiresPermission((android.Manifest.permission.MODIFY_PHONE_STATE))
+    @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
     public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE            = 0x00001000;
 
     /**
@@ -328,26 +332,36 @@
      * Listen for call disconnect causes which contains {@link DisconnectCause} and
      * {@link PreciseDisconnectCause}.
      *
+     * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
+     * or the calling app has carrier privileges
+     * (see {@link TelephonyManager#hasCarrierPrivileges}).
+     *
      */
     @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
     public static final int LISTEN_CALL_DISCONNECT_CAUSES                  = 0x02000000;
 
     /**
      * Listen for changes to the call attributes of a currently active call.
-     * {@more}
-     * Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE
-     * READ_PRECISE_PHONE_STATE}
+     *
+     * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
+     * or the calling app has carrier privileges
+     * (see {@link TelephonyManager#hasCarrierPrivileges}).
      *
      * @see #onCallAttributesChanged
      * @hide
      */
     @SystemApi
+    @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
     public static final int LISTEN_CALL_ATTRIBUTES_CHANGED                 = 0x04000000;
 
     /**
      * Listen for IMS call disconnect causes which contains
      * {@link android.telephony.ims.ImsReasonInfo}
      *
+     * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
+     * or the calling app has carrier privileges
+     * (see {@link TelephonyManager#hasCarrierPrivileges}).
+     *
      * @see #onImsCallDisconnectCauseChanged(ImsReasonInfo)
      */
     @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
diff --git a/core/java/android/timezone/CountryTimeZones.java b/core/java/android/timezone/CountryTimeZones.java
index ada59d6..e5bbdf4 100644
--- a/core/java/android/timezone/CountryTimeZones.java
+++ b/core/java/android/timezone/CountryTimeZones.java
@@ -43,6 +43,7 @@
     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
     public static final class TimeZoneMapping {
 
+        @NonNull
         private libcore.timezone.CountryTimeZones.TimeZoneMapping mDelegate;
 
         TimeZoneMapping(libcore.timezone.CountryTimeZones.TimeZoneMapping delegate) {
diff --git a/core/java/android/timezone/TelephonyLookup.java b/core/java/android/timezone/TelephonyLookup.java
index 39dbe85..eebccf4 100644
--- a/core/java/android/timezone/TelephonyLookup.java
+++ b/core/java/android/timezone/TelephonyLookup.java
@@ -36,12 +36,8 @@
     @GuardedBy("sLock")
     private static TelephonyLookup sInstance;
 
-    @NonNull
-    private final libcore.timezone.TelephonyLookup mDelegate;
-
     /**
-     * Obtains an instance for use when resolving telephony time zone information. This method never
-     * returns {@code null}.
+     * Obtains an instance for use when resolving telephony time zone information.
      */
     @NonNull
     public static TelephonyLookup getInstance() {
@@ -53,6 +49,9 @@
         }
     }
 
+    @NonNull
+    private final libcore.timezone.TelephonyLookup mDelegate;
+
     private TelephonyLookup(@NonNull libcore.timezone.TelephonyLookup delegate) {
         mDelegate = Objects.requireNonNull(delegate);
     }
diff --git a/core/java/android/timezone/TelephonyNetworkFinder.java b/core/java/android/timezone/TelephonyNetworkFinder.java
index a81a516..079d088 100644
--- a/core/java/android/timezone/TelephonyNetworkFinder.java
+++ b/core/java/android/timezone/TelephonyNetworkFinder.java
@@ -23,7 +23,7 @@
 import java.util.Objects;
 
 /**
- * A class that can find telephony networks loaded via {@link TelephonyLookup}.
+ * A class that can find telephony network information loaded via {@link TelephonyLookup}.
  *
  * @hide
  */
diff --git a/core/java/android/timezone/TimeZoneFinder.java b/core/java/android/timezone/TimeZoneFinder.java
index 15dfe62..9327b00 100644
--- a/core/java/android/timezone/TimeZoneFinder.java
+++ b/core/java/android/timezone/TimeZoneFinder.java
@@ -22,8 +22,10 @@
 
 import com.android.internal.annotations.GuardedBy;
 
+import java.util.Objects;
+
 /**
- * A class that can be used to find time zones.
+ * A class that can be used to find time zones using information like country and offset.
  *
  * @hide
  */
@@ -34,15 +36,8 @@
     @GuardedBy("sLock")
     private static TimeZoneFinder sInstance;
 
-    private final libcore.timezone.TimeZoneFinder mDelegate;
-
-    private TimeZoneFinder(libcore.timezone.TimeZoneFinder delegate) {
-        mDelegate = delegate;
-    }
-
     /**
-     * Obtains an instance for use when resolving telephony time zone information. This method never
-     * returns {@code null}.
+     * Obtains the singleton instance.
      */
     @NonNull
     public static TimeZoneFinder getInstance() {
@@ -54,6 +49,22 @@
         return sInstance;
     }
 
+    @NonNull
+    private final libcore.timezone.TimeZoneFinder mDelegate;
+
+    private TimeZoneFinder(@NonNull libcore.timezone.TimeZoneFinder delegate) {
+        mDelegate = Objects.requireNonNull(delegate);
+    }
+
+    /**
+     * Returns the IANA rules version associated with the data. If there is no version information
+     * or there is a problem reading the file then {@code null} is returned.
+     */
+    @Nullable
+    public String getIanaVersion() {
+        return mDelegate.getIanaVersion();
+    }
+
     /**
      * Returns a {@link CountryTimeZones} object associated with the specified country code.
      * Caching is handled as needed. If the country code is not recognized or there is an error
diff --git a/core/java/android/timezone/TzDataSetVersion.java b/core/java/android/timezone/TzDataSetVersion.java
new file mode 100644
index 0000000..aba7c4c
--- /dev/null
+++ b/core/java/android/timezone/TzDataSetVersion.java
@@ -0,0 +1,154 @@
+/*
+ * 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 android.timezone;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.IOException;
+import java.util.Objects;
+
+/**
+ * Version information associated with the set of time zone data on a device.
+ *
+ * <p>Time Zone Data Sets have a major ({@link #getFormatMajorVersion()}) and minor
+ * ({@link #currentFormatMinorVersion()}) version number:
+ * <ul>
+ *   <li>Major version numbers are mutually incompatible. e.g. v2 is not compatible with a v1 or a
+ *   v3 device.</li>
+ *   <li>Minor version numbers are backwards compatible. e.g. a v2.2 data set will work
+ *   on a v2.1 device but not a v2.3 device. The minor version is reset to 1 when the major version
+ *   is incremented.</li>
+ * </ul>
+ *
+ * <p>Data sets contain time zone rules and other data associated wtih a tzdb release
+ * ({@link #getRulesVersion()}) and an additional Android-specific revision number
+ * ({@link #getRevision()}).
+ *
+ * <p>See platform/system/timezone/README.android for more information.
+ * @hide
+ */
+@VisibleForTesting
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+public final class TzDataSetVersion {
+
+    /**
+     * Returns the major tz data format version supported by this device.
+     */
+    public static int currentFormatMajorVersion() {
+        return libcore.timezone.TzDataSetVersion.currentFormatMajorVersion();
+    }
+
+    /**
+     * Returns the minor tz data format version supported by this device.
+     */
+    public static int currentFormatMinorVersion() {
+        return libcore.timezone.TzDataSetVersion.currentFormatMinorVersion();
+    }
+
+    /**
+     * Returns true if the version information provided would be compatible with this device, i.e.
+     * with the current system image, and set of active modules.
+     */
+    public static boolean isCompatibleWithThisDevice(TzDataSetVersion tzDataSetVersion) {
+        return libcore.timezone.TzDataSetVersion.isCompatibleWithThisDevice(
+                tzDataSetVersion.mDelegate);
+    }
+
+    /**
+     * Reads the current Android time zone data set version file.
+     */
+    @NonNull
+    public static TzDataSetVersion read() throws IOException, TzDataSetException {
+        try {
+            return new TzDataSetVersion(
+                    libcore.timezone.TzDataSetVersion.readTimeZoneModuleVersion());
+        } catch (libcore.timezone.TzDataSetVersion.TzDataSetException e) {
+            throw new TzDataSetException(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * A checked exception used in connection with time zone data sets.
+     * @hide
+     */
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    public static class TzDataSetException extends Exception {
+
+        /** Creates an instance with a message. */
+        public TzDataSetException(String message) {
+            super(message);
+        }
+
+        /** Creates an instance with a message and a cause. */
+        public TzDataSetException(String message, Throwable cause) {
+            super(message, cause);
+        }
+    }
+
+    @NonNull
+    private final libcore.timezone.TzDataSetVersion mDelegate;
+
+    private TzDataSetVersion(@NonNull libcore.timezone.TzDataSetVersion delegate) {
+        mDelegate = Objects.requireNonNull(delegate);
+    }
+
+    /** Returns the major version number. See {@link TzDataSetVersion}. */
+    public int getFormatMajorVersion() {
+        return mDelegate.formatMajorVersion;
+    }
+
+    /** Returns the minor version number. See {@link TzDataSetVersion}. */
+    public int getFormatMinorVersion() {
+        return mDelegate.formatMinorVersion;
+    }
+
+    /** Returns the tzdb version string. See {@link TzDataSetVersion}. */
+    @NonNull
+    public String getRulesVersion() {
+        return mDelegate.rulesVersion;
+    }
+
+    /** Returns the Android revision. See {@link TzDataSetVersion}. */
+    public int getRevision() {
+        return mDelegate.revision;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        TzDataSetVersion that = (TzDataSetVersion) o;
+        return mDelegate.equals(that.mDelegate);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mDelegate);
+    }
+
+    @Override
+    public String toString() {
+        return mDelegate.toString();
+    }
+}
diff --git a/core/java/android/timezone/ZoneInfoDb.java b/core/java/android/timezone/ZoneInfoDb.java
new file mode 100644
index 0000000..eb191e8
--- /dev/null
+++ b/core/java/android/timezone/ZoneInfoDb.java
@@ -0,0 +1,66 @@
+/*
+ * 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 android.timezone;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.Objects;
+
+/**
+ * Android's internal factory for java.util.TimeZone objects. Provides access to core library time
+ * zone metadata not available via {@link java.util.TimeZone}.
+ *
+ * @hide
+ */
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+public final class ZoneInfoDb {
+
+    private static Object sLock = new Object();
+    @GuardedBy("sLock")
+    private static ZoneInfoDb sInstance;
+
+    /**
+     * Obtains the singleton instance.
+     */
+    @NonNull
+    public static ZoneInfoDb getInstance() {
+        synchronized (sLock) {
+            if (sInstance == null) {
+                sInstance = new ZoneInfoDb(libcore.timezone.ZoneInfoDB.getInstance());
+            }
+        }
+        return sInstance;
+    }
+
+    @NonNull
+    private final libcore.timezone.ZoneInfoDB mDelegate;
+
+    private ZoneInfoDb(libcore.timezone.ZoneInfoDB delegate) {
+        mDelegate = Objects.requireNonNull(delegate);
+    }
+
+    /**
+     * Returns the tzdb version in use.
+     */
+    @NonNull
+    public String getVersion() {
+        return mDelegate.getVersion();
+    }
+}
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
index 0558204..37dd781 100644
--- a/core/java/android/util/TimeUtils.java
+++ b/core/java/android/util/TimeUtils.java
@@ -89,7 +89,7 @@
      *
      * <p>The list returned may be different from other on-device sources like
      * {@link android.icu.util.TimeZone#getRegion(String)} as it can be curated to avoid
-     * contentious mappings.
+     * contentious or obsolete mappings.
      *
      * @param countryCode the ISO 3166-1 alpha-2 code for the country as can be obtained using
      *     {@link java.util.Locale#getCountry()}
diff --git a/core/java/android/view/ImeFocusController.java b/core/java/android/view/ImeFocusController.java
index 5c494c1..271566a 100644
--- a/core/java/android/view/ImeFocusController.java
+++ b/core/java/android/view/ImeFocusController.java
@@ -38,6 +38,7 @@
     private boolean mHasImeFocus = false;
     private View mServedView;
     private View mNextServedView;
+    private InputMethodManagerDelegate mDelegate;
 
     @UiThread
     ImeFocusController(@NonNull ViewRootImpl viewRootImpl) {
@@ -45,7 +46,11 @@
     }
 
     private InputMethodManagerDelegate getImmDelegate() {
-        return mViewRootImpl.mContext.getSystemService(InputMethodManager.class).getDelegate();
+        if (mDelegate == null) {
+            mDelegate = mViewRootImpl.mContext.getSystemService(
+                    InputMethodManager.class).getDelegate();
+        }
+        return mDelegate;
     }
 
     @UiThread
diff --git a/core/java/android/view/inputmethod/InputMethod.java b/core/java/android/view/inputmethod/InputMethod.java
index cf494ae..91e15c1 100644
--- a/core/java/android/view/inputmethod/InputMethod.java
+++ b/core/java/android/view/inputmethod/InputMethod.java
@@ -27,6 +27,7 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.util.Log;
+import android.view.View;
 import android.view.autofill.AutofillId;
 
 import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
@@ -298,7 +299,30 @@
      * until deliberated dismissed by the user in its UI.
      */
     public static final int SHOW_FORCED = 0x00002;
-    
+
+    /**
+     * Request that any soft input part of the input method be shown to the user.
+     *
+     * @param flags Provides additional information about the show request.
+     * Currently may be 0 or have the bit {@link #SHOW_EXPLICIT} set.
+     * @param resultReceiver The client requesting the show may wish to
+     * be told the impact of their request, which should be supplied here.
+     * The result code should be
+     * {@link InputMethodManager#RESULT_UNCHANGED_SHOWN InputMethodManager.RESULT_UNCHANGED_SHOWN},
+     * {@link InputMethodManager#RESULT_UNCHANGED_HIDDEN InputMethodManager.RESULT_UNCHANGED_HIDDEN},
+     * {@link InputMethodManager#RESULT_SHOWN InputMethodManager.RESULT_SHOWN}, or
+     * {@link InputMethodManager#RESULT_HIDDEN InputMethodManager.RESULT_HIDDEN}.
+     * @param showInputToken an opaque {@link android.os.Binder} token to identify which API call
+     *        of {@link InputMethodManager#showSoftInput(View, int)} is associated with
+     *        this callback.
+     * @hide
+     */
+    @MainThread
+    default public void showSoftInputWithToken(int flags, ResultReceiver resultReceiver,
+            IBinder showInputToken) {
+        showSoftInput(flags, resultReceiver);
+    }
+
     /**
      * Request that any soft input part of the input method be shown to the user.
      * 
@@ -314,7 +338,7 @@
      */
     @MainThread
     public void showSoftInput(int flags, ResultReceiver resultReceiver);
-    
+
     /**
      * Request that any soft input part of the input method be hidden from the user.
      * @param flags Provides additional information about the show request.
@@ -336,4 +360,12 @@
      */
     @MainThread
     public void changeInputMethodSubtype(InputMethodSubtype subtype);
+
+    /**
+     * Update token of the client window requesting {@link #showSoftInput(int, ResultReceiver)}
+     * @param showInputToken dummy app window token for window requesting
+     *        {@link InputMethodManager#showSoftInput(View, int)}
+     * @hide
+     */
+    public void setCurrentShowInputToken(IBinder showInputToken);
 }
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 904e736..307abd2 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -59,12 +59,12 @@
 import android.util.Printer;
 import android.util.SparseArray;
 import android.view.Display;
+import android.view.ImeFocusController;
 import android.view.ImeInsetsSourceConsumer;
 import android.view.InputChannel;
 import android.view.InputEvent;
 import android.view.InputEventSender;
 import android.view.KeyEvent;
-import android.view.ImeFocusController;
 import android.view.View;
 import android.view.ViewRootImpl;
 import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
@@ -562,14 +562,23 @@
         public boolean startInput(@StartInputReason int startInputReason, View focusedView,
                 @StartInputFlags int startInputFlags, @SoftInputModeFlags int softInputMode,
                 int windowFlags) {
+            final View servedView;
             synchronized (mH) {
                 mCurrentTextBoxAttribute = null;
                 mCompletions = null;
                 mServedConnecting = true;
-                if (getServedViewLocked() != null && !getServedViewLocked().onCheckIsTextEditor()) {
-                    // servedView has changed and it's not editable.
-                    maybeCallServedViewChangedLocked(null);
-                }
+                servedView = getServedViewLocked();
+            }
+            if (servedView != null && servedView.getHandler() != null) {
+                // Make sure View checks should be on the UI thread.
+                servedView.getHandler().post(() -> {
+                    if (!servedView.onCheckIsTextEditor()) {
+                        // servedView has changed and it's not editable.
+                        synchronized (mH) {
+                            maybeCallServedViewChangedLocked(null);
+                        }
+                    }
+                });
             }
             return startInputInner(startInputReason,
                     focusedView != null ? focusedView.getWindowToken() : null, startInputFlags,
@@ -607,21 +616,22 @@
                 mWindowFocusGainFuture.cancel(false /* mayInterruptIfRunning */);
             }
             mWindowFocusGainFuture = mStartInputWorker.submit(() -> {
-                synchronized (mH) {
-                    if (mCurRootView == null) {
+                final ImeFocusController controller = getFocusController();
+                if (controller == null) {
+                    return;
+                }
+                if (controller.checkFocus(forceNewFocus1, false)) {
+                    // We need to restart input on the current focus view.  This
+                    // should be done in conjunction with telling the system service
+                    // about the window gaining focus, to help make the transition
+                    // smooth.
+                    if (startInput(StartInputReason.WINDOW_FOCUS_GAIN,
+                            focusedView, startInputFlags, softInputMode, windowFlags)) {
                         return;
                     }
-                    if (mCurRootView.getImeFocusController().checkFocus(forceNewFocus1, false)) {
-                        // We need to restart input on the current focus view.  This
-                        // should be done in conjunction with telling the system service
-                        // about the window gaining focus, to help make the transition
-                        // smooth.
-                        if (startInput(StartInputReason.WINDOW_FOCUS_GAIN,
-                                focusedView, startInputFlags, softInputMode, windowFlags)) {
-                            return;
-                        }
-                    }
+                }
 
+                synchronized (mH) {
                     // For some reason we didn't do a startInput + windowFocusGain, so
                     // we'll just do a window focus gain and call it a day.
                     try {
@@ -716,6 +726,15 @@
         }
     }
 
+    private ImeFocusController getFocusController() {
+        synchronized (mH) {
+            if (mCurRootView != null) {
+                return mCurRootView.getImeFocusController();
+            }
+            return null;
+        }
+    }
+
     /**
      * Returns {@code true} when the given view has been served by Input Method.
      */
@@ -1617,7 +1636,8 @@
             }
 
             try {
-                return mService.showSoftInput(mClient, flags, resultReceiver);
+                return mService.showSoftInput(
+                        mClient, view.getWindowToken(), flags, resultReceiver);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -1639,7 +1659,8 @@
             Log.w(TAG, "showSoftInputUnchecked() is a hidden method, which will be removed "
                     + "soon. If you are using android.support.v7.widget.SearchView, please update "
                     + "to version 26.0 or newer version.");
-            mService.showSoftInput(mClient, flags, resultReceiver);
+            mService.showSoftInput(
+                    mClient, mCurRootView.getView().getWindowToken(), flags, resultReceiver);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1793,6 +1814,12 @@
         startInputInner(StartInputReason.APP_CALLED_RESTART_INPUT_API, null, 0, 0, 0);
     }
 
+    /**
+     * Called when {@link DelegateImpl#startInput}, {@link #restartInput(View)},
+     * {@link #MSG_BIND} or {@link #MSG_UNBIND}.
+     * Note that this method should *NOT* be called inside of {@code mH} lock to prevent start input
+     * background thread may blocked by other methods which already inside {@code mH} lock.
+     */
     boolean startInputInner(@StartInputReason int startInputReason,
             @Nullable IBinder windowGainingFocus, @StartInputFlags int startInputFlags,
             @SoftInputModeFlags int softInputMode, int windowFlags) {
@@ -1976,15 +2003,16 @@
     }
 
     /**
+     * Check the next served view from {@link ImeFocusController} if needs to start input.
+     * Note that this method should *NOT* be called inside of {@code mH} lock to prevent start input
+     * background thread may blocked by other methods which already inside {@code mH} lock.
      * @hide
      */
     @UnsupportedAppUsage
     public void checkFocus() {
-        synchronized (mH) {
-            if (mCurRootView != null) {
-                mCurRootView.getImeFocusController().checkFocus(false /* forceNewFocus */,
-                        true /* startInput */);
-            }
+        final ImeFocusController controller = getFocusController();
+        if (controller != null) {
+            controller.checkFocus(false /* forceNewFocus */, true /* startInput */);
         }
     }
 
diff --git a/core/java/android/webkit/PacProcessor.java b/core/java/android/webkit/PacProcessor.java
index fe8bbb8..5ef450f 100644
--- a/core/java/android/webkit/PacProcessor.java
+++ b/core/java/android/webkit/PacProcessor.java
@@ -54,5 +54,5 @@
      *         For example: "PROXY xxx.xxx.xxx.xxx:xx; SOCKS yyy.yyy.yyy:yy".
      */
     @Nullable
-    String makeProxyRequest(@NonNull String url);
+    String findProxyForUrl(@NonNull String url);
 }
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 2732b2e..b10631b 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -220,7 +220,9 @@
 
     private final boolean mHapticTextHandleEnabled;
 
-    private final MagnifierMotionAnimator mMagnifierAnimator;
+    @Nullable
+    private MagnifierMotionAnimator mMagnifierAnimator;
+
     private final Runnable mUpdateMagnifierRunnable = new Runnable() {
         @Override
         public void run() {
@@ -397,12 +399,6 @@
         mHapticTextHandleEnabled = mTextView.getContext().getResources().getBoolean(
                 com.android.internal.R.bool.config_enableHapticTextHandle);
 
-        if (FLAG_USE_MAGNIFIER) {
-            final Magnifier magnifier =
-                    Magnifier.createBuilderWithOldMagnifierDefaults(mTextView).build();
-            mMagnifierAnimator = new MagnifierMotionAnimator(magnifier);
-        }
-
         mCursorControlEnabled = AppGlobals.getIntCoreSetting(
                 WidgetFlags.KEY_ENABLE_CURSOR_CONTROL , 0) != 0;
         if (TextView.DEBUG_CURSOR) {
@@ -421,6 +417,63 @@
         return mCursorControlEnabled;
     }
 
+    // Lazy creates the magnifier animator.
+    private MagnifierMotionAnimator getMagnifierAnimator() {
+        if (FLAG_USE_MAGNIFIER && mMagnifierAnimator == null) {
+            // Lazy creates the magnifier instance because it requires the text height which cannot
+            // be measured at the time of Editor instance being created.
+            final Magnifier.Builder builder = shouldUseNewMagnifier()
+                    ? createBuilderWithInlineMagnifierDefaults()
+                    : Magnifier.createBuilderWithOldMagnifierDefaults(mTextView);
+            mMagnifierAnimator = new MagnifierMotionAnimator(builder.build());
+        }
+        return mMagnifierAnimator;
+    }
+
+    private boolean shouldUseNewMagnifier() {
+        // TODO: use a separate flag to enable new magnifier.
+        return mCursorControlEnabled;
+    }
+
+    private Magnifier.Builder createBuilderWithInlineMagnifierDefaults() {
+        final Magnifier.Builder params = new Magnifier.Builder(mTextView);
+
+        // TODO: supports changing the height/width dynamically because the text height can be
+        // dynamically changed.
+        final Paint.FontMetrics fontMetrics = mTextView.getPaint().getFontMetrics();
+        final float sourceHeight = fontMetrics.descent - fontMetrics.ascent;
+        final float zoom = 1.5f;
+        final float widthHeightRatio = 5.5f;
+        // Slightly increase the height to avoid tooLargeTextForMagnifier() returns true.
+        int height = (int)(sourceHeight * zoom) + 2;
+        int width = (int)(widthHeightRatio * height);
+
+
+        params.setFishEyeStyle()
+                .setSize(width, height)
+                .setSourceSize(width, Math.round(sourceHeight))
+                .setElevation(0)
+                .setInitialZoom(zoom)
+                .setClippingEnabled(false);
+
+        final Context context = mTextView.getContext();
+        final TypedArray a = context.obtainStyledAttributes(
+                null, com.android.internal.R.styleable.Magnifier,
+                com.android.internal.R.attr.magnifierStyle, 0);
+        params.setDefaultSourceToMagnifierOffset(
+                a.getDimensionPixelSize(
+                        com.android.internal.R.styleable.Magnifier_magnifierHorizontalOffset, 0),
+                a.getDimensionPixelSize(
+                        com.android.internal.R.styleable.Magnifier_magnifierVerticalOffset, 0));
+        a.recycle();
+
+        return params.setSourceBounds(
+                Magnifier.SOURCE_BOUND_MAX_VISIBLE,
+                Magnifier.SOURCE_BOUND_MAX_IN_SURFACE,
+                Magnifier.SOURCE_BOUND_MAX_VISIBLE,
+                Magnifier.SOURCE_BOUND_MAX_IN_SURFACE);
+    }
+
     ParcelableParcel saveInstanceState() {
         ParcelableParcel state = new ParcelableParcel(getClass().getClassLoader());
         Parcel parcel = state.getParcel();
@@ -5022,7 +5075,7 @@
         }
 
         protected final void updateMagnifier(@NonNull final MotionEvent event) {
-            if (mMagnifierAnimator == null) {
+            if (getMagnifierAnimator() == null) {
                 return;
             }
 
@@ -5036,6 +5089,16 @@
                 mTextView.invalidateCursorPath();
                 suspendBlink();
 
+                if (shouldUseNewMagnifier()) {
+                    // Calculates the line bounds as the content source bounds to the magnifier.
+                    Layout layout = mTextView.getLayout();
+                    int line = layout.getLineForOffset(getCurrentCursorOffset());
+                    int lineLeft = (int) layout.getLineLeft(line);
+                    lineLeft += mTextView.getTotalPaddingLeft() - mTextView.getScrollX();
+                    int lineRight = (int) layout.getLineRight(line);
+                    lineRight -= mTextView.getTotalPaddingRight() + mTextView.getScrollX();
+                    mMagnifierAnimator.mMagnifier.setSourceHorizontalBounds(lineLeft, lineRight);
+                }
                 mMagnifierAnimator.show(showPosInView.x, showPosInView.y);
                 updateHandlesVisibility();
             } else {
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index 2924dd9..57b63a7 100644
--- a/core/java/android/widget/Magnifier.java
+++ b/core/java/android/widget/Magnifier.java
@@ -140,6 +140,18 @@
     // The lock used to synchronize the UI and render threads when a #dismiss is performed.
     private final Object mDestroyLock = new Object();
 
+    // Members for new styled magnifier (Eloquent style).
+
+    // Whether the magnifier is in new style.
+    private boolean mIsFishEyeStyle;
+    // The width of the cut region on the left edge of the pixel copy source rect.
+    private int mLeftCutWidth = 0;
+    // The width of the cut region on the right edge of the pixel copy source rect.
+    private int mRightCutWidth = 0;
+    // The horizontal bounds of the content source in pixels, relative to the view.
+    private int mLeftBound = Integer.MIN_VALUE;
+    private int mRightBound = Integer.MAX_VALUE;
+
     /**
      * Initializes a magnifier.
      *
@@ -198,8 +210,14 @@
         mWindowWidth = params.mWidth;
         mWindowHeight = params.mHeight;
         mZoom = params.mZoom;
-        mSourceWidth = Math.round(mWindowWidth / mZoom);
-        mSourceHeight = Math.round(mWindowHeight / mZoom);
+        mIsFishEyeStyle = params.mIsFishEyeStyle;
+        if (params.mSourceWidth > 0 && params.mSourceHeight > 0) {
+            mSourceWidth = params.mSourceWidth;
+            mSourceHeight = params.mSourceHeight;
+        } else {
+            mSourceWidth = Math.round(mWindowWidth / mZoom);
+            mSourceHeight = Math.round(mWindowHeight / mZoom);
+        }
         mWindowElevation = params.mElevation;
         mWindowCornerRadius = params.mCornerRadius;
         mOverlay = params.mOverlay;
@@ -221,6 +239,18 @@
     }
 
     /**
+     * Sets the horizontal bounds of the source when showing the magnifier.
+     * This is used for new style magnifier. e.g. limit the source bounds by the text line bounds.
+     *
+     * @param left the left of the bounds, relative to the view.
+     * @param right the right of the bounds, relative to the view.
+     */
+    void setSourceHorizontalBounds(int left, int right) {
+        mLeftBound = left;
+        mRightBound = right;
+    }
+
+    /**
      * Shows the magnifier on the screen. The method takes the coordinates of the center
      * of the content source going to be magnified and copied to the magnifier. The coordinates
      * are relative to the top left corner of the magnified view. The magnifier will be
@@ -265,20 +295,37 @@
 
         obtainSurfaces();
         obtainContentCoordinates(sourceCenterX, sourceCenterY);
+
+        int startX = mClampedCenterZoomCoords.x - mSourceWidth / 2;
+        final int startY = mClampedCenterZoomCoords.y - mSourceHeight / 2;
+
+        if (mIsFishEyeStyle) {
+            // The magnifier center is the same as source center in new style.
+            magnifierCenterX = mClampedCenterZoomCoords.x - mViewCoordinatesInSurface[0];
+            magnifierCenterY = mClampedCenterZoomCoords.y - mViewCoordinatesInSurface[1];
+            // Gets the startX for new style, which should be bounded by the horizontal bounds.
+            // Also calculates the left/right cut width for pixel copy.
+            final int left = startX;
+            final int right = startX + mSourceWidth;
+            final int leftBound = mViewCoordinatesInSurface[0] + Math.max(0, mLeftBound);
+            final int rightBound =
+                    mViewCoordinatesInSurface[0] + Math.min(mView.getWidth(), mRightBound);
+            startX = Math.max(left, leftBound);
+            mLeftCutWidth = Math.max(0, leftBound - left);
+            mRightCutWidth = Math.max(0, right - rightBound);
+        }
         obtainWindowCoordinates(magnifierCenterX, magnifierCenterY);
 
-        final int startX = mClampedCenterZoomCoords.x - mSourceWidth / 2;
-        final int startY = mClampedCenterZoomCoords.y - mSourceHeight / 2;
         if (sourceCenterX != mPrevShowSourceCoords.x || sourceCenterY != mPrevShowSourceCoords.y
                 || mDirtyState) {
             if (mWindow == null) {
                 synchronized (mLock) {
                     mWindow = new InternalPopupWindow(mView.getContext(), mView.getDisplay(),
-                            mParentSurface.mSurfaceControl, mWindowWidth, mWindowHeight,
+                            mParentSurface.mSurfaceControl, mWindowWidth, mWindowHeight, mZoom,
                             mWindowElevation, mWindowCornerRadius,
                             mOverlay != null ? mOverlay : new ColorDrawable(Color.TRANSPARENT),
                             Handler.getMain() /* draw the magnifier on the UI thread */, mLock,
-                            mCallback);
+                            mCallback, mIsFishEyeStyle);
                 }
             }
             performPixelCopy(startX, startY, true /* update window position */);
@@ -387,7 +434,7 @@
     public void setZoom(@FloatRange(from = 0f) float zoom) {
         Preconditions.checkArgumentPositive(zoom, "Zoom should be positive");
         mZoom = zoom;
-        mSourceWidth = Math.round(mWindowWidth / mZoom);
+        mSourceWidth = mIsFishEyeStyle ? mWindowWidth : Math.round(mWindowWidth / mZoom);
         mSourceHeight = Math.round(mWindowHeight / mZoom);
         mDirtyState = true;
     }
@@ -634,8 +681,10 @@
         resolvedBottom = Math.max(resolvedBottom, resolvedTop + mSourceHeight);
 
         // Finally compute the coordinates of the source center.
-        mClampedCenterZoomCoords.x = Math.max(resolvedLeft + mSourceWidth / 2, Math.min(
-                zoomCenterX, resolvedRight - mSourceWidth / 2));
+        mClampedCenterZoomCoords.x = mIsFishEyeStyle
+                ? Math.max(resolvedLeft, Math.min(zoomCenterX, resolvedRight))
+                : Math.max(resolvedLeft + mSourceWidth / 2, Math.min(
+                        zoomCenterX, resolvedRight - mSourceWidth / 2));
         mClampedCenterZoomCoords.y = Math.max(resolvedTop + mSourceHeight / 2, Math.min(
                 zoomCenterY, resolvedBottom - mSourceHeight / 2));
     }
@@ -678,11 +727,22 @@
         // Perform the pixel copy.
         mPixelCopyRequestRect.set(startXInSurface,
                 startYInSurface,
-                startXInSurface + mSourceWidth,
+                startXInSurface + mSourceWidth - mLeftCutWidth - mRightCutWidth,
                 startYInSurface + mSourceHeight);
+        mPrevStartCoordsInSurface.x = startXInSurface;
+        mPrevStartCoordsInSurface.y = startYInSurface;
+        mDirtyState = false;
+
         final InternalPopupWindow currentWindowInstance = mWindow;
+        if (mPixelCopyRequestRect.width() == 0) {
+            // If the copy rect is empty, updates an empty bitmap to the window.
+            mWindow.updateContent(
+                    Bitmap.createBitmap(mSourceWidth, mSourceHeight, Bitmap.Config.ALPHA_8));
+            return;
+        }
         final Bitmap bitmap =
-                Bitmap.createBitmap(mSourceWidth, mSourceHeight, Bitmap.Config.ARGB_8888);
+                Bitmap.createBitmap(mSourceWidth - mLeftCutWidth - mRightCutWidth,
+                        mSourceHeight, Bitmap.Config.ARGB_8888);
         PixelCopy.request(mContentCopySurface.mSurface, mPixelCopyRequestRect, bitmap,
                 result -> {
                     if (result != PixelCopy.SUCCESS) {
@@ -696,15 +756,25 @@
                         }
                         if (updateWindowPosition) {
                             // TODO: pull the position update outside #performPixelCopy
-                            mWindow.setContentPositionForNextDraw(windowCoords.x, windowCoords.y);
+                            mWindow.setContentPositionForNextDraw(windowCoords.x,
+                                    windowCoords.y);
                         }
-                        mWindow.updateContent(bitmap);
+                        if (bitmap.getWidth() < mSourceWidth) {
+                            // When bitmap width has been cut, re-fills it with full width bitmap.
+                            // This only happens in new styled magnifier.
+                            final Bitmap newBitmap = Bitmap.createBitmap(
+                                    mSourceWidth, bitmap.getHeight(), bitmap.getConfig());
+                            final Canvas can = new Canvas(newBitmap);
+                            final Rect dstRect = new Rect(mLeftCutWidth, 0,
+                                    mSourceWidth - mRightCutWidth, bitmap.getHeight());
+                            can.drawBitmap(bitmap, null, dstRect, null);
+                            mWindow.updateContent(newBitmap);
+                        } else {
+                            mWindow.updateContent(bitmap);
+                        }
                     }
                 },
                 sPixelCopyHandlerThread.getThreadHandler());
-        mPrevStartCoordsInSurface.x = startXInSurface;
-        mPrevStartCoordsInSurface.y = startYInSurface;
-        mDirtyState = false;
     }
 
     private void onPixelCopyFailed() {
@@ -790,9 +860,6 @@
         // The size of the content of the magnifier.
         private final int mContentWidth;
         private final int mContentHeight;
-        // The size of the allocated surface.
-        private final int mSurfaceWidth;
-        private final int mSurfaceHeight;
         // The insets of the content inside the allocated surface.
         private final int mOffsetX;
         private final int mOffsetY;
@@ -815,9 +882,6 @@
         private final Handler mHandler;
         // The callback to be run after the next draw.
         private Callback mCallback;
-        // The position of the magnifier content when the last draw was requested.
-        private int mLastDrawContentPositionX;
-        private int mLastDrawContentPositionY;
 
         // Members below describe the state of the magnifier. Reads/writes to them
         // have to be synchronized between the UI thread and the thread that handles
@@ -838,10 +902,19 @@
         // The current content of the magnifier. It is mBitmap + mOverlay, only used for testing.
         private Bitmap mCurrentContent;
 
+        private final float mZoom;
+        // Whether is in the new magnifier style.
+        private boolean mIsFishEyeStyle;
+        // The mesh matrix for the fish-eye effect.
+        private float[] mMesh;
+        private int mMeshWidth;
+        private int mMeshHeight;
+
         InternalPopupWindow(final Context context, final Display display,
                 final SurfaceControl parentSurfaceControl, final int width, final int height,
-                final float elevation, final float cornerRadius, final Drawable overlay,
-                final Handler handler, final Object lock, final Callback callback) {
+                final float zoom, final float elevation, final float cornerRadius,
+                final Drawable overlay, final Handler handler, final Object lock,
+                final Callback callback, final boolean isFishEyeStyle) {
             mDisplay = display;
             mOverlay = overlay;
             mLock = lock;
@@ -849,15 +922,16 @@
 
             mContentWidth = width;
             mContentHeight = height;
+            mZoom = zoom;
             mOffsetX = (int) (1.05f * elevation);
             mOffsetY = (int) (1.05f * elevation);
             // Setup the surface we will use for drawing the content and shadow.
-            mSurfaceWidth = mContentWidth + 2 * mOffsetX;
-            mSurfaceHeight = mContentHeight + 2 * mOffsetY;
+            final int surfaceWidth = mContentWidth + 2 * mOffsetX;
+            final int surfaceHeight = mContentHeight + 2 * mOffsetY;
             mSurfaceSession = new SurfaceSession();
             mSurfaceControl = new SurfaceControl.Builder(mSurfaceSession)
                     .setFormat(PixelFormat.TRANSLUCENT)
-                    .setBufferSize(mSurfaceWidth, mSurfaceHeight)
+                    .setBufferSize(surfaceWidth, surfaceHeight)
                     .setName("magnifier surface")
                     .setFlags(SurfaceControl.HIDDEN)
                     .setParent(parentSurfaceControl)
@@ -904,6 +978,38 @@
             mHandler = handler;
             mMagnifierUpdater = this::doDraw;
             mFrameDrawScheduled = false;
+            mIsFishEyeStyle = isFishEyeStyle;
+
+            if (mIsFishEyeStyle) {
+                createMeshMatrixForFishEyeEffect();
+            }
+        }
+
+        private void createMeshMatrixForFishEyeEffect() {
+            mMeshWidth = mZoom < 1.5f ? 5 : 4;
+            mMeshHeight = 6;
+            final float w = mContentWidth;
+            final float h = mContentHeight;
+            final float dx = (w - mZoom * w * (mMeshWidth - 2) / mMeshWidth) / 2;
+            mMesh = new float[2 * (mMeshWidth + 1) * (mMeshHeight + 1)];
+            for (int i = 0; i < 2 * (mMeshWidth + 1) * (mMeshHeight + 1); i += 2) {
+                // Calculates X value.
+                final int colIndex = i % (2 * (mMeshWidth + 1)) / 2;
+                if (colIndex == 0) {
+                    mMesh[i] = 0;
+                } else if (colIndex == mMeshWidth) {
+                    mMesh[i] = w;
+                } else {
+                    mMesh[i] = (colIndex - 1) * (w - 2 * dx) / (mMeshWidth - 2) + dx;
+                }
+                // Calculates Y value.
+                final int rowIndex = i / 2 / (mMeshWidth + 1);
+                final float y0 = colIndex == 0 || colIndex == mMeshWidth
+                        ? (h - h / mZoom) / 2 : 0;
+                final float dy = colIndex == 0 || colIndex == mMeshWidth
+                        ? h / mZoom / mMeshHeight : h / mMeshHeight;
+                mMesh[i + 1] = y0 + rowIndex * dy;
+            }
         }
 
         private RenderNode createRenderNodeForBitmap(final String name,
@@ -1060,15 +1166,19 @@
                 final RecordingCanvas canvas =
                         mBitmapRenderNode.beginRecording(mContentWidth, mContentHeight);
                 try {
-                    final Rect srcRect = new Rect(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
-                    final Rect dstRect = new Rect(0, 0, mContentWidth, mContentHeight);
-                    final Paint paint = new Paint();
-                    paint.setFilterBitmap(true);
-                    canvas.drawBitmap(mBitmap, srcRect, dstRect, paint);
+                    if (mIsFishEyeStyle) {
+                        canvas.drawBitmapMesh(
+                                mBitmap, mMeshWidth, mMeshHeight, mMesh, 0, null, 0, null);
+                    } else {
+                        final Rect srcRect = new Rect(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
+                        final Rect dstRect = new Rect(0, 0, mContentWidth, mContentHeight);
+                        final Paint paint = new Paint();
+                        paint.setFilterBitmap(true);
+                        canvas.drawBitmap(mBitmap, srcRect, dstRect, paint);
+                    }
                 } finally {
                     mBitmapRenderNode.endRecording();
                 }
-
                 if (mPendingWindowPositionUpdate || mFirstDraw) {
                     // If the window has to be shown or moved, defer this until the next draw.
                     final boolean firstDraw = mFirstDraw;
@@ -1094,13 +1204,14 @@
                         }
                         mTransaction.apply();
                     };
-                    mRenderer.setLightCenter(mDisplay, pendingX, pendingY);
+                    if (!mIsFishEyeStyle) {
+                        // The new style magnifier doesn't need the light/shadow.
+                        mRenderer.setLightCenter(mDisplay, pendingX, pendingY);
+                    }
                 } else {
                     callback = null;
                 }
 
-                mLastDrawContentPositionX = mWindowPositionX + mOffsetX;
-                mLastDrawContentPositionY = mWindowPositionY + mOffsetY;
                 mFrameDrawScheduled = false;
             }
 
@@ -1149,6 +1260,9 @@
         private @SourceBound int mTopContentBound;
         private @SourceBound int mRightContentBound;
         private @SourceBound int  mBottomContentBound;
+        private boolean mIsFishEyeStyle;
+        private int mSourceWidth;
+        private int mSourceHeight;
 
         /**
          * Construct a new builder for {@link Magnifier} objects.
@@ -1177,6 +1291,7 @@
             mTopContentBound = SOURCE_BOUND_MAX_VISIBLE;
             mRightContentBound = SOURCE_BOUND_MAX_VISIBLE;
             mBottomContentBound = SOURCE_BOUND_MAX_VISIBLE;
+            mIsFishEyeStyle = false;
         }
 
         /**
@@ -1339,6 +1454,25 @@
         }
 
         /**
+         * Sets the source width/height.
+         */
+        @NonNull
+        Builder setSourceSize(int width, int height) {
+            mSourceWidth = width;
+            mSourceHeight = height;
+            return this;
+        }
+
+        /**
+         * Sets the magnifier as the new fish-eye style.
+         */
+        @NonNull
+        Builder setFishEyeStyle() {
+            mIsFishEyeStyle = true;
+            return this;
+        }
+
+        /**
          * Builds a {@link Magnifier} instance based on the configuration of this {@link Builder}.
          */
         public @NonNull Magnifier build() {
diff --git a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
index e27ff00..20cd7c2 100644
--- a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
+++ b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
@@ -41,5 +41,5 @@
     boolean shouldOfferSwitchingToNextInputMethod();
     void notifyUserAction();
     void reportPreRendered(in EditorInfo info);
-    void applyImeVisibility(boolean setVisible);
+    void applyImeVisibility(IBinder showInputToken, boolean setVisible);
 }
diff --git a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
index d42c607..9eeef96 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
@@ -23,6 +23,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Log;
+import android.view.View;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodSubtype;
 
@@ -368,18 +369,20 @@
     }
 
     /**
-     * Calls {@link IInputMethodPrivilegedOperations#applyImeVisibility(boolean)}.
+     * Calls {@link IInputMethodPrivilegedOperations#applyImeVisibility(IBinder, boolean)}.
      *
+     * @param showInputToken dummy token that maps to window requesting
+     *        {@link android.view.inputmethod.InputMethodManager#showSoftInput(View, int)}
      * @param setVisible {@code true} to set IME visible, else hidden.
      */
     @AnyThread
-    public void applyImeVisibility(boolean setVisible) {
+    public void applyImeVisibility(IBinder showInputToken, boolean setVisible) {
         final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
         if (ops == null) {
             return;
         }
         try {
-            ops.applyImeVisibility(setVisible);
+            ops.applyImeVisibility(showInputToken, setVisible);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/com/android/internal/logging/InstanceId.java b/core/java/com/android/internal/logging/InstanceId.java
new file mode 100644
index 0000000..85dbac3
--- /dev/null
+++ b/core/java/com/android/internal/logging/InstanceId.java
@@ -0,0 +1,50 @@
+/*
+ * 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.logging;
+
+import android.annotation.Nullable;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * An opaque identifier used to disambiguate which logs refer to a particular instance of some
+ * UI element. Useful when there might be multiple instances simultaneously active.
+ * Obtain from InstanceIdSequence.
+ */
+public class InstanceId {
+    private int mId;
+    protected InstanceId(int id) {
+        mId = id;
+    }
+    @VisibleForTesting
+    public int getId() {
+        return mId;
+    }
+
+    @Override
+    public int hashCode() {
+        return mId;
+    }
+
+    @Override
+    public boolean equals(@Nullable Object obj) {
+        if (!(obj instanceof InstanceId)) {
+            return false;
+        }
+        return mId == ((InstanceId) obj).mId;
+    }
+}
diff --git a/core/java/com/android/internal/logging/InstanceIdSequence.java b/core/java/com/android/internal/logging/InstanceIdSequence.java
new file mode 100644
index 0000000..2e78ed8
--- /dev/null
+++ b/core/java/com/android/internal/logging/InstanceIdSequence.java
@@ -0,0 +1,52 @@
+/*
+ * 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.logging;
+
+import static java.lang.Math.max;
+import static java.lang.Math.min;
+
+import java.security.SecureRandom;
+import java.util.Random;
+
+/**
+ * Generates random InstanceIds in range [0, instanceIdMax) for passing to
+ * UiEventLogger.logWithInstanceId(). Holds a SecureRandom, which self-seeds on
+ * first use; try to give it a long lifetime. Safe for concurrent use.
+ */
+public class InstanceIdSequence {
+    // At most 20 bits: ~1m possibilities, ~0.5% probability of collision in 100 values
+    private static final int INSTANCE_ID_MAX = 1 << 20;
+    protected final int mInstanceIdMax;
+    private final Random mRandom = new SecureRandom();
+
+    /**
+     * Constructs a sequence with identifiers [0, instanceIdMax).  Capped at INSTANCE_ID_MAX.
+     * @param instanceIdMax Limiting value of identifiers. Normally positive: otherwise you get
+     *                      an all-zero sequence.
+     */
+    public InstanceIdSequence(int instanceIdMax) {
+        mInstanceIdMax = min(max(0, instanceIdMax), INSTANCE_ID_MAX);
+    }
+
+    /**
+     * Gets the next instance from the sequence.  Safe for concurrent use.
+     * @return new InstanceId
+     */
+    public InstanceId newInstanceId() {
+        return new InstanceId(mRandom.nextInt(mInstanceIdMax));
+    }
+}
diff --git a/core/java/com/android/internal/logging/UiEventLogger.java b/core/java/com/android/internal/logging/UiEventLogger.java
index 3a450de..48d2bc2 100644
--- a/core/java/com/android/internal/logging/UiEventLogger.java
+++ b/core/java/com/android/internal/logging/UiEventLogger.java
@@ -49,4 +49,15 @@
      * @param packageName the package name of the relevant app, if known (null otherwise).
      */
     void log(@NonNull UiEventEnum event, int uid, @Nullable String packageName);
+
+    /**
+     * Log an event with package information and an instance ID.
+     * Does nothing if event.getId() <= 0.
+     * @param event an enum implementing UiEventEnum interface.
+     * @param uid the uid of the relevant app, if known (0 otherwise).
+     * @param packageName the package name of the relevant app, if known (null otherwise).
+     * @param instance An identifier obtained from an InstanceIdSequence.
+     */
+    void logWithInstanceId(@NonNull UiEventEnum event, int uid, @Nullable String packageName,
+            @NonNull InstanceId instance);
 }
diff --git a/core/java/com/android/internal/logging/UiEventLoggerImpl.java b/core/java/com/android/internal/logging/UiEventLoggerImpl.java
index bdf460c..fe758a8 100644
--- a/core/java/com/android/internal/logging/UiEventLoggerImpl.java
+++ b/core/java/com/android/internal/logging/UiEventLoggerImpl.java
@@ -36,4 +36,14 @@
             StatsLog.write(StatsLog.UI_EVENT_REPORTED, eventID, uid, packageName);
         }
     }
+
+    @Override
+    public void logWithInstanceId(UiEventEnum event, int uid, String packageName,
+            InstanceId instance) {
+        final int eventID = event.getId();
+        if (eventID > 0) {
+            StatsLog.write(StatsLog.UI_EVENT_REPORTED, eventID, uid, packageName,
+                    instance.getId());
+        }
+    }
 }
diff --git a/core/java/com/android/internal/logging/testing/InstanceIdSequenceFake.java b/core/java/com/android/internal/logging/testing/InstanceIdSequenceFake.java
new file mode 100644
index 0000000..0fd40b9
--- /dev/null
+++ b/core/java/com/android/internal/logging/testing/InstanceIdSequenceFake.java
@@ -0,0 +1,56 @@
+/*
+ * 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.logging.testing;
+
+import android.annotation.SuppressLint;
+
+import com.android.internal.logging.InstanceId;
+import com.android.internal.logging.InstanceIdSequence;
+
+/**
+ * A fake implementation of InstanceIdSequence that returns 0, 1, 2, ...
+ */
+public class InstanceIdSequenceFake extends InstanceIdSequence {
+
+    public InstanceIdSequenceFake(int instanceIdMax) {
+        super(instanceIdMax);
+    }
+
+    /**
+     * Extend InstanceId to add a constructor we can call, strictly for testing purposes.
+     * Public so that tests can check whether the InstanceIds they see are fake.
+     */
+    public static class InstanceIdFake extends InstanceId {
+        @SuppressLint("VisibleForTests")  // This is test infrastructure, which ought to count
+        InstanceIdFake(int id) {
+            super(id);
+        }
+    }
+
+    private int mNextId = 0;
+
+    @Override
+    public InstanceId newInstanceId() {
+        synchronized (this) {
+            ++mNextId;
+            if (mNextId >= mInstanceIdMax) {
+                mNextId = 0;
+            }
+            return new InstanceIdFake(mNextId);
+        }
+    }
+}
diff --git a/core/java/com/android/internal/logging/testing/UiEventLoggerFake.java b/core/java/com/android/internal/logging/testing/UiEventLoggerFake.java
index 6be5b81..130ee64 100644
--- a/core/java/com/android/internal/logging/testing/UiEventLoggerFake.java
+++ b/core/java/com/android/internal/logging/testing/UiEventLoggerFake.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.logging.testing;
 
+import com.android.internal.logging.InstanceId;
 import com.android.internal.logging.UiEventLogger;
 
 import java.util.LinkedList;
@@ -34,15 +35,24 @@
         public final int eventId;
         public final int uid;
         public final String packageName;
+        public final InstanceId instanceId;  // Used only for WithInstanceId variant
 
-        public FakeUiEvent(int eventId, int uid, String packageName) {
+        FakeUiEvent(int eventId, int uid, String packageName) {
             this.eventId = eventId;
             this.uid = uid;
             this.packageName = packageName;
+            this.instanceId = null;
+        }
+
+        FakeUiEvent(int eventId, int uid, String packageName, InstanceId instanceId) {
+            this.eventId = eventId;
+            this.uid = uid;
+            this.packageName = packageName;
+            this.instanceId = instanceId;
         }
     }
 
-    private Queue<FakeUiEvent> mLogs = new LinkedList<FakeUiEvent>();
+    private Queue<FakeUiEvent> mLogs = new LinkedList<>();
 
     public Queue<FakeUiEvent> getLogs() {
         return mLogs;
@@ -60,4 +70,13 @@
             mLogs.offer(new FakeUiEvent(eventId, uid, packageName));
         }
     }
+
+    @Override
+    public void logWithInstanceId(UiEventLogger.UiEventEnum event, int uid, String packageName,
+            InstanceId instance) {
+        final int eventId = event.getId();
+        if (eventId > 0) {
+            mLogs.offer(new FakeUiEvent(eventId, uid, packageName, instance));
+        }
+    }
 }
diff --git a/core/java/com/android/internal/view/IInputMethod.aidl b/core/java/com/android/internal/view/IInputMethod.aidl
index 58aaa80..475a321 100644
--- a/core/java/com/android/internal/view/IInputMethod.aidl
+++ b/core/java/com/android/internal/view/IInputMethod.aidl
@@ -54,7 +54,7 @@
 
     void revokeSession(IInputMethodSession session);
 
-    void showSoftInput(int flags, in ResultReceiver resultReceiver);
+    void showSoftInput(in IBinder showInputToken, int flags, in ResultReceiver resultReceiver);
 
     void hideSoftInput(int flags, in ResultReceiver resultReceiver);
 
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index c29e823..0337ddd 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -41,7 +41,7 @@
             boolean allowsImplicitlySelectedSubtypes);
     InputMethodSubtype getLastInputMethodSubtype();
 
-    boolean showSoftInput(in IInputMethodClient client, int flags,
+    boolean showSoftInput(in IInputMethodClient client, IBinder windowToken, int flags,
             in ResultReceiver resultReceiver);
     boolean hideSoftInput(in IInputMethodClient client, int flags,
             in ResultReceiver resultReceiver);
diff --git a/core/jni/android/graphics/apex/android_bitmap.cpp b/core/jni/android/graphics/apex/android_bitmap.cpp
index b8e04a7..3c7691b 100644
--- a/core/jni/android/graphics/apex/android_bitmap.cpp
+++ b/core/jni/android/graphics/apex/android_bitmap.cpp
@@ -123,98 +123,10 @@
     return getInfo(bitmap->info(), bitmap->rowBytes());
 }
 
-namespace {
-static bool nearlyEqual(float a, float b) {
-    // By trial and error, this is close enough to match for the ADataSpaces we
-    // compare for.
-    return ::fabs(a - b) < .002f;
-}
-
-static bool nearlyEqual(const skcms_TransferFunction& x, const skcms_TransferFunction& y) {
-    return nearlyEqual(x.g, y.g)
-        && nearlyEqual(x.a, y.a)
-        && nearlyEqual(x.b, y.b)
-        && nearlyEqual(x.c, y.c)
-        && nearlyEqual(x.d, y.d)
-        && nearlyEqual(x.e, y.e)
-        && nearlyEqual(x.f, y.f);
-}
-
-static bool nearlyEqual(const skcms_Matrix3x3& x, const skcms_Matrix3x3& y) {
-    for (int i = 0; i < 3; i++) {
-        for (int j = 0; j < 3; j++) {
-            if (!nearlyEqual(x.vals[i][j], y.vals[i][j])) return false;
-        }
-    }
-    return true;
-}
-
-static constexpr skcms_TransferFunction k2Dot6 = {2.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
-
-// Skia's SkNamedGamut::kDCIP3 is based on a white point of D65. This gamut
-// matches the white point used by ColorSpace.Named.DCIP3.
-static constexpr skcms_Matrix3x3 kDCIP3 = {{
-        {0.486143, 0.323835, 0.154234},
-        {0.226676, 0.710327, 0.0629966},
-        {0.000800549, 0.0432385, 0.78275},
-}};
-} // anonymous namespace
-
 ADataSpace ABitmap_getDataSpace(ABitmap* bitmapHandle) {
     Bitmap* bitmap = TypeCast::toBitmap(bitmapHandle);
     const SkImageInfo& info = bitmap->info();
-    SkColorSpace* colorSpace = info.colorSpace();
-    if (!colorSpace) {
-        return ADATASPACE_UNKNOWN;
-    }
-
-    if (colorSpace->isSRGB()) {
-        if (info.colorType() == kRGBA_F16_SkColorType) {
-            return ADATASPACE_SCRGB;
-        }
-        return ADATASPACE_SRGB;
-    }
-
-    skcms_TransferFunction fn;
-    LOG_ALWAYS_FATAL_IF(!colorSpace->isNumericalTransferFn(&fn));
-
-    skcms_Matrix3x3 gamut;
-    LOG_ALWAYS_FATAL_IF(!colorSpace->toXYZD50(&gamut));
-
-    if (nearlyEqual(gamut, SkNamedGamut::kSRGB)) {
-        if (nearlyEqual(fn, SkNamedTransferFn::kLinear)) {
-            // Skia doesn't differentiate amongst the RANGES. In Java, we associate
-            // LINEAR_EXTENDED_SRGB with F16, and LINEAR_SRGB with other Configs.
-            // Make the same association here.
-            if (info.colorType() == kRGBA_F16_SkColorType) {
-                return ADATASPACE_SCRGB_LINEAR;
-            }
-            return ADATASPACE_SRGB_LINEAR;
-        }
-
-        if (nearlyEqual(fn, SkNamedTransferFn::kRec2020)) {
-            return ADATASPACE_BT709;
-        }
-    }
-
-    if (nearlyEqual(fn, SkNamedTransferFn::kSRGB) && nearlyEqual(gamut, SkNamedGamut::kDCIP3)) {
-        return ADATASPACE_DISPLAY_P3;
-    }
-
-    if (nearlyEqual(fn, SkNamedTransferFn::k2Dot2) && nearlyEqual(gamut, SkNamedGamut::kAdobeRGB)) {
-        return ADATASPACE_ADOBE_RGB;
-    }
-
-    if (nearlyEqual(fn, SkNamedTransferFn::kRec2020) &&
-        nearlyEqual(gamut, SkNamedGamut::kRec2020)) {
-        return ADATASPACE_BT2020;
-    }
-
-    if (nearlyEqual(fn, k2Dot6) && nearlyEqual(gamut, kDCIP3)) {
-        return ADATASPACE_DCI_P3;
-    }
-
-    return ADATASPACE_UNKNOWN;
+    return (ADataSpace)uirenderer::ColorSpaceToADataSpace(info.colorSpace(), info.colorType());
 }
 
 AndroidBitmapInfo ABitmap_getInfoFromJava(JNIEnv* env, jobject bitmapObj) {
diff --git a/core/jni/android_media_AudioAttributes.cpp b/core/jni/android_media_AudioAttributes.cpp
index b87a34d..b616ffc 100644
--- a/core/jni/android_media_AudioAttributes.cpp
+++ b/core/jni/android_media_AudioAttributes.cpp
@@ -48,11 +48,14 @@
     jfieldID    mFormattedTags; // AudioAttributes.mFormattedTags
 } gAudioAttributesFields;
 
+static struct { jmethodID isSystemUsage; } gAudioAttributesClassMethods;
+
 static jclass gAudioAttributesBuilderClass;
 static jmethodID gAudioAttributesBuilderCstor;
 static struct {
     jmethodID build;
     jmethodID setUsage;
+    jmethodID setSystemUsage;
     jmethodID setInternalCapturePreset;
     jmethodID setContentType;
     jmethodID setFlags;
@@ -109,9 +112,17 @@
     if (jAttributeBuilder.get() == nullptr) {
         return (jint)AUDIO_JAVA_ERROR;
     }
-    env->CallObjectMethod(jAttributeBuilder.get(),
-                          gAudioAttributesBuilderMethods.setUsage,
-                          attributes.usage);
+
+    const bool isSystemUsage = env->CallStaticBooleanMethod(gAudioAttributesClass,
+                                                      gAudioAttributesClassMethods.isSystemUsage,
+                                                      attributes.usage);
+    if (isSystemUsage) {
+        env->CallObjectMethod(jAttributeBuilder.get(),
+                              gAudioAttributesBuilderMethods.setSystemUsage, attributes.usage);
+    } else {
+        env->CallObjectMethod(jAttributeBuilder.get(), gAudioAttributesBuilderMethods.setUsage,
+                              attributes.usage);
+    }
     env->CallObjectMethod(jAttributeBuilder.get(),
                           gAudioAttributesBuilderMethods.setInternalCapturePreset,
                           attributes.source);
@@ -168,6 +179,9 @@
 {
     jclass audioAttributesClass = FindClassOrDie(env, kClassPathName);
     gAudioAttributesClass = MakeGlobalRefOrDie(env, audioAttributesClass);
+    gAudioAttributesClassMethods.isSystemUsage =
+            GetStaticMethodIDOrDie(env, gAudioAttributesClass, "isSystemUsage", "(I)Z");
+
     gAudioAttributesFields.mUsage = GetFieldIDOrDie(env, audioAttributesClass, "mUsage", "I");
     gAudioAttributesFields.mSource = GetFieldIDOrDie(env, audioAttributesClass, "mSource", "I");
     gAudioAttributesFields.mContentType =
@@ -186,6 +200,9 @@
     gAudioAttributesBuilderMethods.setUsage = GetMethodIDOrDie(
                 env, audioAttributesBuilderClass, "setUsage",
                 "(I)Landroid/media/AudioAttributes$Builder;");
+    gAudioAttributesBuilderMethods.setSystemUsage =
+            GetMethodIDOrDie(env, audioAttributesBuilderClass, "setSystemUsage",
+                             "(I)Landroid/media/AudioAttributes$Builder;");
     gAudioAttributesBuilderMethods.setInternalCapturePreset = GetMethodIDOrDie(
                 env, audioAttributesBuilderClass, "setInternalCapturePreset",
                 "(I)Landroid/media/AudioAttributes$Builder;");
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index c4ee195..e266fe6 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -2239,6 +2239,31 @@
     return AudioSystem::isHapticPlaybackSupported();
 }
 
+static jint android_media_AudioSystem_setSupportedSystemUsages(JNIEnv *env, jobject thiz,
+                                                               jintArray systemUsages) {
+    std::vector<audio_usage_t> nativeSystemUsagesVector;
+
+    if (systemUsages == nullptr) {
+        return (jint) AUDIO_JAVA_BAD_VALUE;
+    }
+
+    int *nativeSystemUsages = nullptr;
+    nativeSystemUsages = env->GetIntArrayElements(systemUsages, 0);
+
+    if (nativeSystemUsages != nullptr) {
+        jsize len = env->GetArrayLength(systemUsages);
+        for (size_t i = 0; i < len; i++) {
+            audio_usage_t nativeAudioUsage =
+                    static_cast<audio_usage_t>(nativeSystemUsages[i]);
+            nativeSystemUsagesVector.push_back(nativeAudioUsage);
+        }
+        env->ReleaseIntArrayElements(systemUsages, nativeSystemUsages, 0);
+    }
+
+    status_t status = AudioSystem::setSupportedSystemUsages(nativeSystemUsagesVector);
+    return (jint)nativeToJavaStatus(status);
+}
+
 static jint
 android_media_AudioSystem_setAllowedCapturePolicy(JNIEnv *env, jobject thiz, jint uid, jint flags) {
     return AudioSystem::setAllowedCapturePolicy(uid, flags);
@@ -2430,6 +2455,7 @@
     {"isHapticPlaybackSupported", "()Z", (void *)android_media_AudioSystem_isHapticPlaybackSupported},
     {"getHwOffloadEncodingFormatsSupportedForA2DP", "(Ljava/util/ArrayList;)I",
                     (void*)android_media_AudioSystem_getHwOffloadEncodingFormatsSupportedForA2DP},
+    {"setSupportedSystemUsages", "([I)I", (void *)android_media_AudioSystem_setSupportedSystemUsages},
     {"setAllowedCapturePolicy", "(II)I", (void *)android_media_AudioSystem_setAllowedCapturePolicy},
     {"setRttEnabled",       "(Z)I",     (void *)android_media_AudioSystem_setRttEnabled},
     {"setAudioHalPids",  "([I)I", (void *)android_media_AudioSystem_setAudioHalPids},
diff --git a/core/jni/android_service_DataLoaderService.cpp b/core/jni/android_service_DataLoaderService.cpp
index a62d127..b307a73 100644
--- a/core/jni/android_service_DataLoaderService.cpp
+++ b/core/jni/android_service_DataLoaderService.cpp
@@ -35,24 +35,24 @@
 static jboolean nativeStartDataLoader(JNIEnv* env,
                                       jobject thiz,
                                       jint storageId) {
-    return DataLoaderService_OnStart(storageId);
+    return DataLoaderService_OnStart(env, storageId);
 }
 
 static jboolean nativeStopDataLoader(JNIEnv* env,
                                      jobject thiz,
                                      jint storageId) {
-    return DataLoaderService_OnStop(storageId);
+    return DataLoaderService_OnStop(env, storageId);
 }
 
 static jboolean nativeDestroyDataLoader(JNIEnv* env,
                                         jobject thiz,
                                         jint storageId) {
-    return DataLoaderService_OnDestroy(storageId);
+    return DataLoaderService_OnDestroy(env, storageId);
 }
 
 
 static jboolean nativePrepareImage(JNIEnv* env, jobject thiz, jint storageId, jobject addedFiles, jobject removedFiles) {
-    return DataLoaderService_OnPrepareImage(storageId, addedFiles, removedFiles);
+    return DataLoaderService_OnPrepareImage(env, storageId, addedFiles, removedFiles);
 }
 
 static void nativeWriteData(JNIEnv* env,
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index ee6e8c4..89dbca8 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -50,11 +50,14 @@
 #include <pwd.h>
 #include <signal.h>
 #include <string.h>
+#include <sys/epoll.h>
 #include <sys/errno.h>
 #include <sys/resource.h>
 #include <sys/stat.h>
+#include <sys/syscall.h>
 #include <sys/sysinfo.h>
 #include <sys/types.h>
+#include <time.h>
 #include <unistd.h>
 
 #define GUARD_THREAD_PRIORITY 0
@@ -1271,39 +1274,78 @@
     return removeAllProcessGroups();
 }
 
+static void throwErrnoException(JNIEnv* env, const char* functionName, int error) {
+    ScopedLocalRef<jstring> detailMessage(env, env->NewStringUTF(functionName));
+    if (detailMessage.get() == NULL) {
+        // Not really much we can do here. We're probably dead in the water,
+        // but let's try to stumble on...
+        env->ExceptionClear();
+    }
+    static jclass errnoExceptionClass =
+            MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/system/ErrnoException"));
+
+    static jmethodID errnoExceptionCtor =
+            GetMethodIDOrDie(env, errnoExceptionClass, "<init>", "(Ljava/lang/String;I)V");
+
+    jobject exception =
+            env->NewObject(errnoExceptionClass, errnoExceptionCtor, detailMessage.get(), error);
+    env->Throw(reinterpret_cast<jthrowable>(exception));
+}
+
+// Wrapper function to the syscall pidfd_open, which creates a file
+// descriptor that refers to the process whose PID is specified in pid.
+static inline int sys_pidfd_open(pid_t pid, unsigned int flags) {
+    return syscall(__NR_pidfd_open, pid, flags);
+}
+
+static jboolean android_os_Process_nativePidFdOpen(JNIEnv* env, jobject, jint pid, jint flags) {
+    int fd = sys_pidfd_open(pid, flags);
+    if (fd < 0) {
+        throwErrnoException(env, "nativePidFdOpen", errno);
+        return -1;
+    }
+    return fd;
+}
+
 static const JNINativeMethod methods[] = {
-    {"getUidForName",       "(Ljava/lang/String;)I", (void*)android_os_Process_getUidForName},
-    {"getGidForName",       "(Ljava/lang/String;)I", (void*)android_os_Process_getGidForName},
-    {"setThreadPriority",   "(II)V", (void*)android_os_Process_setThreadPriority},
-    {"setThreadScheduler",  "(III)V", (void*)android_os_Process_setThreadScheduler},
-    {"setCanSelfBackground", "(Z)V", (void*)android_os_Process_setCanSelfBackground},
-    {"setThreadPriority",   "(I)V", (void*)android_os_Process_setCallingThreadPriority},
-    {"getThreadPriority",   "(I)I", (void*)android_os_Process_getThreadPriority},
-    {"getThreadScheduler",   "(I)I", (void*)android_os_Process_getThreadScheduler},
-    {"setThreadGroup",      "(II)V", (void*)android_os_Process_setThreadGroup},
-    {"setThreadGroupAndCpuset", "(II)V", (void*)android_os_Process_setThreadGroupAndCpuset},
-    {"setProcessGroup",     "(II)V", (void*)android_os_Process_setProcessGroup},
-    {"getProcessGroup",     "(I)I", (void*)android_os_Process_getProcessGroup},
-    {"getExclusiveCores",   "()[I", (void*)android_os_Process_getExclusiveCores},
-    {"setSwappiness",   "(IZ)Z", (void*)android_os_Process_setSwappiness},
-    {"setArgV0",    "(Ljava/lang/String;)V", (void*)android_os_Process_setArgV0},
-    {"setUid", "(I)I", (void*)android_os_Process_setUid},
-    {"setGid", "(I)I", (void*)android_os_Process_setGid},
-    {"sendSignal", "(II)V", (void*)android_os_Process_sendSignal},
-    {"sendSignalQuiet", "(II)V", (void*)android_os_Process_sendSignalQuiet},
-    {"getFreeMemory", "()J", (void*)android_os_Process_getFreeMemory},
-    {"getTotalMemory", "()J", (void*)android_os_Process_getTotalMemory},
-    {"readProcLines", "(Ljava/lang/String;[Ljava/lang/String;[J)V", (void*)android_os_Process_readProcLines},
-    {"getPids", "(Ljava/lang/String;[I)[I", (void*)android_os_Process_getPids},
-    {"readProcFile", "(Ljava/lang/String;[I[Ljava/lang/String;[J[F)Z", (void*)android_os_Process_readProcFile},
-    {"parseProcLine", "([BII[I[Ljava/lang/String;[J[F)Z", (void*)android_os_Process_parseProcLine},
-    {"getElapsedCpuTime", "()J", (void*)android_os_Process_getElapsedCpuTime},
-    {"getPss", "(I)J", (void*)android_os_Process_getPss},
-    {"getRss", "(I)[J", (void*)android_os_Process_getRss},
-    {"getPidsForCommands", "([Ljava/lang/String;)[I", (void*)android_os_Process_getPidsForCommands},
-    //{"setApplicationObject", "(Landroid/os/IBinder;)V", (void*)android_os_Process_setApplicationObject},
-    {"killProcessGroup", "(II)I", (void*)android_os_Process_killProcessGroup},
-    {"removeAllProcessGroups", "()V", (void*)android_os_Process_removeAllProcessGroups},
+        {"getUidForName", "(Ljava/lang/String;)I", (void*)android_os_Process_getUidForName},
+        {"getGidForName", "(Ljava/lang/String;)I", (void*)android_os_Process_getGidForName},
+        {"setThreadPriority", "(II)V", (void*)android_os_Process_setThreadPriority},
+        {"setThreadScheduler", "(III)V", (void*)android_os_Process_setThreadScheduler},
+        {"setCanSelfBackground", "(Z)V", (void*)android_os_Process_setCanSelfBackground},
+        {"setThreadPriority", "(I)V", (void*)android_os_Process_setCallingThreadPriority},
+        {"getThreadPriority", "(I)I", (void*)android_os_Process_getThreadPriority},
+        {"getThreadScheduler", "(I)I", (void*)android_os_Process_getThreadScheduler},
+        {"setThreadGroup", "(II)V", (void*)android_os_Process_setThreadGroup},
+        {"setThreadGroupAndCpuset", "(II)V", (void*)android_os_Process_setThreadGroupAndCpuset},
+        {"setProcessGroup", "(II)V", (void*)android_os_Process_setProcessGroup},
+        {"getProcessGroup", "(I)I", (void*)android_os_Process_getProcessGroup},
+        {"getExclusiveCores", "()[I", (void*)android_os_Process_getExclusiveCores},
+        {"setSwappiness", "(IZ)Z", (void*)android_os_Process_setSwappiness},
+        {"setArgV0", "(Ljava/lang/String;)V", (void*)android_os_Process_setArgV0},
+        {"setUid", "(I)I", (void*)android_os_Process_setUid},
+        {"setGid", "(I)I", (void*)android_os_Process_setGid},
+        {"sendSignal", "(II)V", (void*)android_os_Process_sendSignal},
+        {"sendSignalQuiet", "(II)V", (void*)android_os_Process_sendSignalQuiet},
+        {"getFreeMemory", "()J", (void*)android_os_Process_getFreeMemory},
+        {"getTotalMemory", "()J", (void*)android_os_Process_getTotalMemory},
+        {"readProcLines", "(Ljava/lang/String;[Ljava/lang/String;[J)V",
+         (void*)android_os_Process_readProcLines},
+        {"getPids", "(Ljava/lang/String;[I)[I", (void*)android_os_Process_getPids},
+        {"readProcFile", "(Ljava/lang/String;[I[Ljava/lang/String;[J[F)Z",
+         (void*)android_os_Process_readProcFile},
+        {"parseProcLine", "([BII[I[Ljava/lang/String;[J[F)Z",
+         (void*)android_os_Process_parseProcLine},
+        {"getElapsedCpuTime", "()J", (void*)android_os_Process_getElapsedCpuTime},
+        {"getPss", "(I)J", (void*)android_os_Process_getPss},
+        {"getRss", "(I)[J", (void*)android_os_Process_getRss},
+        {"getPidsForCommands", "([Ljava/lang/String;)[I",
+         (void*)android_os_Process_getPidsForCommands},
+        //{"setApplicationObject", "(Landroid/os/IBinder;)V",
+        //(void*)android_os_Process_setApplicationObject},
+        {"killProcessGroup", "(II)I", (void*)android_os_Process_killProcessGroup},
+        {"removeAllProcessGroups", "()V", (void*)android_os_Process_removeAllProcessGroups},
+        {"nativePidFdOpen", "(II)I", (void*)android_os_Process_nativePidFdOpen},
 };
 
 int register_android_os_Process(JNIEnv* env)
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index da8c944..d08cbed 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -56,6 +56,7 @@
 import "frameworks/base/core/proto/android/util/log.proto";
 import "frameworks/base/core/proto/android/privacy.proto";
 import "frameworks/base/core/proto/android/section.proto";
+import "frameworks/base/proto/src/ipconnectivity.proto";
 
 package android.os;
 
@@ -480,6 +481,11 @@
         (section).args = "cpuinfo --proto"
     ];
 
+    optional .clearcut.connectivity.IpConnectivityLog ip_connectivity_metrics = 3049 [
+        (section).type = SECTION_DUMPSYS,
+        (section).args = "connmetrics --proto"
+    ];
+
     // Reserved for OEMs.
     extensions 50000 to 100000;
 }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index da2e078..3c65753 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3231,6 +3231,13 @@
     <permission android:name="android.permission.BIND_NFC_SERVICE"
         android:protectionLevel="signature" />
 
+    <!-- Must be required by a {@link android.service.quickaccesswallet.QuickAccessWalletService}
+         to ensure that only the system can bind to it.
+         <p>Protection level: signature
+    -->
+    <permission android:name="android.permission.BIND_QUICK_ACCESS_WALLET_SERVICE"
+                android:protectionLevel="signature" />
+
     <!-- Must be required by the PrintSpooler to ensure that only the system can bind to it.
          @hide -->
     <permission android:name="android.permission.BIND_PRINT_SPOOLER_SERVICE"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index e0d8492..940e9f1 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -8329,6 +8329,26 @@
         <attr name="successColor" format="color|reference"/>
     </declare-styleable>
 
+    <!-- =============================== -->
+    <!-- QuickAccessWallet attributes -->
+    <!-- =============================== -->
+    <eat-comment />
+
+    <!-- Use <code>quickaccesswallet-service</code> as the root tag of the XML resource
+         that describes a {@link android.service.quickaccesswallet.QuickAccessWalletService},
+         which is referenced from its
+         {@link android.service.quickaccesswallet.QuickAccessWalletService#SERVICE_META_DATA}
+         meta-data entry.
+    -->
+    <declare-styleable name="QuickAccessWalletService">
+        <!-- Fully qualified class name of an activity that allows the user to modify
+             the settings for this service. -->
+        <attr name="settingsActivity"/>
+        <!-- Fully qualified class name of an activity that allows the user to view
+             their entire wallet -->
+        <attr name="targetActivity"/>
+    </declare-styleable>
+
     <!-- Use <code>recognition-service</code> as the root tag of the XML resource that
          describes a {@link android.speech.RecognitionService}, which is referenced from
          its {@link android.speech.RecognitionService#SERVICE_META_DATA} meta-data entry.
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f25f97c..6a00ecb 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -5271,6 +5271,10 @@
     <!-- Description of media type: presentation file, such as PPT. The 'extension' variable is the file name extension. [CHAR LIMIT=32] -->
     <string name="mime_type_presentation_ext"><xliff:g id="extension" example="PDF">%1$s</xliff:g> presentation</string>
 
+    <!-- Strings for Bluetooth service -->
+    <!-- toast message informing user that Bluetooth stays on after airplane mode is turned on. [CHAR LIMIT=NONE] -->
+    <string name="bluetooth_airplane_mode_toast">Bluetooth will stay on during airplane mode</string>
+
     <!-- Strings for car -->
     <!-- String displayed when loading a user in the car [CHAR LIMIT=30] -->
     <string name="car_loading_profile">Loading</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 527798d..7e6eb5d 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3723,6 +3723,9 @@
   <java-symbol type="string" name="mime_type_presentation" />
   <java-symbol type="string" name="mime_type_presentation_ext" />
 
+  <!-- For Bluetooth service -->
+  <java-symbol type="string" name="bluetooth_airplane_mode_toast" />
+
   <!-- For high refresh rate displays -->
   <java-symbol type="integer" name="config_defaultPeakRefreshRate" />
   <java-symbol type="integer" name="config_defaultRefreshRateInZone" />
diff --git a/core/tests/coretests/src/android/content/ApexContextTest.java b/core/tests/coretests/src/android/content/ApexContextTest.java
new file mode 100644
index 0000000..d15c64d
--- /dev/null
+++ b/core/tests/coretests/src/android/content/ApexContextTest.java
@@ -0,0 +1,47 @@
+/*
+ * 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 android.content;
+
+import static org.junit.Assert.assertEquals;
+
+import android.os.UserHandle;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ApexContextTest {
+
+    @Test
+    public void dataDirectoryPathsAreAsExpected() {
+        ApexContext apexContext = ApexContext.getApexContext("my.apex");
+
+        assertEquals("/data/misc/apexdata/my.apex",
+                apexContext.getDeviceProtectedDataDir().getAbsolutePath());
+
+        assertEquals("/data/misc_de/5/apexdata/my.apex",
+                apexContext.getDeviceProtectedDataDirForUser(UserHandle.of(5)).getAbsolutePath());
+
+        assertEquals("/data/misc_ce/16/apexdata/my.apex",
+                apexContext.getCredentialProtectedDataDirForUser(
+                        UserHandle.of(16)).getAbsolutePath());
+    }
+}
diff --git a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
index fab96a1..928e607 100644
--- a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
+++ b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
@@ -16,6 +16,7 @@
 
 package android.graphics.drawable;
 
+import android.annotation.DrawableRes;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
@@ -223,6 +224,7 @@
         final int deviceDensity = Drawable.resolveDensity(r, 0);
         state.setDensity(deviceDensity);
         state.mSrcDensityOverride = mSrcDensityOverride;
+        state.mSourceDrawableId = Resources.getAttributeSetSourceResId(attrs);
 
         final ChildDrawable[] array = state.mChildren;
         for (int i = 0; i < state.mChildren.length; i++) {
@@ -446,6 +448,17 @@
     }
 
     /**
+     * If the drawable was inflated from XML, this returns the resource ID for the drawable
+     *
+     * @hide
+     */
+    @DrawableRes
+    public int getSourceDrawableResId() {
+        final LayerState state = mLayerState;
+        return state == null ? Resources.ID_NULL : state.mSourceDrawableId;
+    }
+
+    /**
      * Inflates child layers using the specified parser.
      */
     private void inflateLayers(@NonNull Resources r, @NonNull XmlPullParser parser,
@@ -944,6 +957,8 @@
         @Config int mChangingConfigurations;
         @Config int mChildrenChangingConfigurations;
 
+        @DrawableRes int mSourceDrawableId = Resources.ID_NULL;
+
         private boolean mCheckedOpacity;
         private int mOpacity;
 
diff --git a/identity/java/android/security/identity/WritableIdentityCredential.java b/identity/java/android/security/identity/WritableIdentityCredential.java
index 5f575b9..e2a389b 100644
--- a/identity/java/android/security/identity/WritableIdentityCredential.java
+++ b/identity/java/android/security/identity/WritableIdentityCredential.java
@@ -31,6 +31,11 @@
  */
 public abstract class WritableIdentityCredential {
     /**
+     * @hide
+     */
+    protected WritableIdentityCredential() {}
+
+    /**
      * Generates and returns an X.509 certificate chain for the CredentialKey which identifies this
      * credential to the issuing authority. The certificate contains an
      * <a href="https://source.android.com/security/keystore/attestation">Android Keystore</a>
diff --git a/libs/hwui/utils/Color.cpp b/libs/hwui/utils/Color.cpp
index c445885..71a27ce 100644
--- a/libs/hwui/utils/Color.cpp
+++ b/libs/hwui/utils/Color.cpp
@@ -108,7 +108,9 @@
     }
 }
 
-// FIXME: Share with the version in android_bitmap.cpp?
+namespace {
+static constexpr skcms_TransferFunction k2Dot6 = {2.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
+
 // Skia's SkNamedGamut::kDCIP3 is based on a white point of D65. This gamut
 // matches the white point used by ColorSpace.Named.DCIP3.
 static constexpr skcms_Matrix3x3 kDCIP3 = {{
@@ -117,6 +119,87 @@
         {0.000800549, 0.0432385, 0.78275},
 }};
 
+static bool nearlyEqual(float a, float b) {
+    // By trial and error, this is close enough to match for the ADataSpaces we
+    // compare for.
+    return ::fabs(a - b) < .002f;
+}
+
+static bool nearlyEqual(const skcms_TransferFunction& x, const skcms_TransferFunction& y) {
+    return nearlyEqual(x.g, y.g)
+        && nearlyEqual(x.a, y.a)
+        && nearlyEqual(x.b, y.b)
+        && nearlyEqual(x.c, y.c)
+        && nearlyEqual(x.d, y.d)
+        && nearlyEqual(x.e, y.e)
+        && nearlyEqual(x.f, y.f);
+}
+
+static bool nearlyEqual(const skcms_Matrix3x3& x, const skcms_Matrix3x3& y) {
+    for (int i = 0; i < 3; i++) {
+        for (int j = 0; j < 3; j++) {
+            if (!nearlyEqual(x.vals[i][j], y.vals[i][j])) return false;
+        }
+    }
+    return true;
+}
+
+} // anonymous namespace
+
+android_dataspace ColorSpaceToADataSpace(SkColorSpace* colorSpace, SkColorType colorType) {
+    if (!colorSpace) {
+        return HAL_DATASPACE_UNKNOWN;
+    }
+
+    if (colorSpace->isSRGB()) {
+        if (colorType == kRGBA_F16_SkColorType) {
+            return HAL_DATASPACE_V0_SCRGB;
+        }
+        return HAL_DATASPACE_V0_SRGB;
+    }
+
+    skcms_TransferFunction fn;
+    LOG_ALWAYS_FATAL_IF(!colorSpace->isNumericalTransferFn(&fn));
+
+    skcms_Matrix3x3 gamut;
+    LOG_ALWAYS_FATAL_IF(!colorSpace->toXYZD50(&gamut));
+
+    if (nearlyEqual(gamut, SkNamedGamut::kSRGB)) {
+        if (nearlyEqual(fn, SkNamedTransferFn::kLinear)) {
+            // Skia doesn't differentiate amongst the RANGES. In Java, we associate
+            // LINEAR_EXTENDED_SRGB with F16, and LINEAR_SRGB with other Configs.
+            // Make the same association here.
+            if (colorType == kRGBA_F16_SkColorType) {
+                return HAL_DATASPACE_V0_SCRGB_LINEAR;
+            }
+            return HAL_DATASPACE_V0_SRGB_LINEAR;
+        }
+
+        if (nearlyEqual(fn, SkNamedTransferFn::kRec2020)) {
+            return HAL_DATASPACE_V0_BT709;
+        }
+    }
+
+    if (nearlyEqual(fn, SkNamedTransferFn::kSRGB) && nearlyEqual(gamut, SkNamedGamut::kDCIP3)) {
+        return HAL_DATASPACE_DISPLAY_P3;
+    }
+
+    if (nearlyEqual(fn, SkNamedTransferFn::k2Dot2) && nearlyEqual(gamut, SkNamedGamut::kAdobeRGB)) {
+        return HAL_DATASPACE_ADOBE_RGB;
+    }
+
+    if (nearlyEqual(fn, SkNamedTransferFn::kRec2020) &&
+        nearlyEqual(gamut, SkNamedGamut::kRec2020)) {
+        return HAL_DATASPACE_BT2020;
+    }
+
+    if (nearlyEqual(fn, k2Dot6) && nearlyEqual(gamut, kDCIP3)) {
+        return HAL_DATASPACE_DCI_P3;
+    }
+
+    return HAL_DATASPACE_UNKNOWN;
+}
+
 sk_sp<SkColorSpace> DataSpaceToColorSpace(android_dataspace dataspace) {
     if (dataspace == HAL_DATASPACE_UNKNOWN) {
         return SkColorSpace::MakeSRGB();
@@ -126,7 +209,7 @@
         // needs to use the locally-defined kDCIP3 gamut, rather than the one in
         // Skia (SkNamedGamut), which is used for other data spaces with
         // HAL_DATASPACE_STANDARD_DCI_P3 (e.g. HAL_DATASPACE_DISPLAY_P3).
-        return SkColorSpace::MakeRGB({2.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, kDCIP3);
+        return SkColorSpace::MakeRGB(k2Dot6, kDCIP3);
     }
 
     skcms_Matrix3x3 gamut;
@@ -165,7 +248,7 @@
         case HAL_DATASPACE_TRANSFER_GAMMA2_2:
             return SkColorSpace::MakeRGB({2.2f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, gamut);
         case HAL_DATASPACE_TRANSFER_GAMMA2_6:
-            return SkColorSpace::MakeRGB({2.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, gamut);
+            return SkColorSpace::MakeRGB(k2Dot6, gamut);
         case HAL_DATASPACE_TRANSFER_GAMMA2_8:
             return SkColorSpace::MakeRGB({2.8f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, gamut);
         case HAL_DATASPACE_TRANSFER_ST2084:
diff --git a/libs/hwui/utils/Color.h b/libs/hwui/utils/Color.h
index 07b5ec8..a76f7e4 100644
--- a/libs/hwui/utils/Color.h
+++ b/libs/hwui/utils/Color.h
@@ -105,6 +105,22 @@
 
 ANDROID_API sk_sp<SkColorSpace> DataSpaceToColorSpace(android_dataspace dataspace);
 
+/**
+ * Return the android_dataspace corresponding to colorSpace.
+ *
+ * Note: This currently only returns android_dataspaces with corresponding
+ * ADataSpaces. The NDK relies on this, so if you need to update it to return
+ * an android_dataspace *without* an ADataSpace, the NDK methods need to be
+ * updated.
+ *
+ * @param colorSpace May be null, in which case this will return
+ *                   HAL_DATASPACE_UNKNOWN.
+ * @param colorType Some SkColorSpaces are associated with more than one
+ *                  android_dataspace. In that case, the SkColorType is used to
+ *                  determine which one to return.
+ */
+ANDROID_API android_dataspace ColorSpaceToADataSpace(SkColorSpace*, SkColorType);
+
 struct Lab {
     float L;
     float a;
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 8cd3c6e..114c0f1 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -99,6 +99,10 @@
     public final static int CONTENT_TYPE_SONIFICATION = 4;
 
     /**
+     * Invalid value, only ever used for an uninitialized usage value
+     */
+    private static final int USAGE_INVALID = -1;
+    /**
      * Usage value to use when the usage is unknown.
      */
     public final static int USAGE_UNKNOWN = 0;
@@ -184,9 +188,43 @@
      * Usage value to use for assistant voice interaction with remote caller on Cell and VoIP calls.
      */
     @SystemApi
-    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    @RequiresPermission(allOf = {
+            android.Manifest.permission.MODIFY_PHONE_STATE,
+            android.Manifest.permission.MODIFY_AUDIO_ROUTING
+    })
     public static final int USAGE_CALL_ASSISTANT = 17;
 
+    private static final int SYSTEM_USAGE_OFFSET = 1000;
+
+    /**
+     * @hide
+     * Usage value to use when the usage is an emergency.
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+    public static final int USAGE_EMERGENCY = SYSTEM_USAGE_OFFSET;
+    /**
+     * @hide
+     * Usage value to use when the usage is a safety sound.
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+    public static final int USAGE_SAFETY = SYSTEM_USAGE_OFFSET + 1;
+    /**
+     * @hide
+     * Usage value to use when the usage is a vehicle status.
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+    public static final int USAGE_VEHICLE_STATUS = SYSTEM_USAGE_OFFSET + 2;
+    /**
+     * @hide
+     * Usage value to use when the usage is an announcement.
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+    public static final int USAGE_ANNOUNCEMENT = SYSTEM_USAGE_OFFSET + 3;
+
     /**
      * IMPORTANT: when adding new usage types, add them to SDK_USAGES and update SUPPRESSIBLE_USAGES
      *            if applicable, as well as audioattributes.proto.
@@ -489,6 +527,20 @@
      * @return one of the values that can be set in {@link Builder#setUsage(int)}
      */
     public int getUsage() {
+        if (isSystemUsage(mUsage)) {
+            return USAGE_UNKNOWN;
+        }
+        return mUsage;
+    }
+
+    /**
+     * @hide
+     * Return the system usage.
+     * @return one of the values that can be set in {@link Builder#setUsage(int)} or
+     * {@link Builder#setSystemUsage(int)}
+     */
+    @SystemApi
+    public int getSystemUsage() {
         return mUsage;
     }
 
@@ -591,7 +643,8 @@
      * {@link MediaPlayer} will use a default usage of {@link AudioAttributes#USAGE_MEDIA}.
      */
     public static class Builder {
-        private int mUsage = USAGE_UNKNOWN;
+        private int mUsage = USAGE_INVALID;
+        private int mSystemUsage = USAGE_INVALID;
         private int mContentType = CONTENT_TYPE_UNKNOWN;
         private int mSource = MediaRecorder.AudioSource.AUDIO_SOURCE_INVALID;
         private int mFlags = 0x0;
@@ -637,7 +690,22 @@
         public AudioAttributes build() {
             AudioAttributes aa = new AudioAttributes();
             aa.mContentType = mContentType;
-            aa.mUsage = mUsage;
+
+            if (mUsage == USAGE_INVALID) {
+                if (mSystemUsage == USAGE_INVALID) {
+                    aa.mUsage = USAGE_UNKNOWN;
+                } else {
+                    aa.mUsage = mSystemUsage;
+                }
+            } else {
+                if (mSystemUsage == USAGE_INVALID) {
+                    aa.mUsage = mUsage;
+                } else {
+                    throw new IllegalArgumentException(
+                            "Cannot set both usage and system usage on same builder");
+                }
+            }
+
             aa.mSource = mSource;
             aa.mFlags = mFlags;
             if (mMuteHapticChannels) {
@@ -667,26 +735,26 @@
         }
 
         /**
-         * Sets the attribute describing what is the intended use of the the audio signal,
+         * Sets the attribute describing what is the intended use of the audio signal,
          * such as alarm or ringtone.
-         * @param usage one of {@link AudioAttributes#USAGE_UNKNOWN},
-         *     {@link AudioAttributes#USAGE_MEDIA},
-         *     {@link AudioAttributes#USAGE_VOICE_COMMUNICATION},
-         *     {@link AudioAttributes#USAGE_VOICE_COMMUNICATION_SIGNALLING},
-         *     {@link AudioAttributes#USAGE_ALARM}, {@link AudioAttributes#USAGE_NOTIFICATION},
-         *     {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE},
-         *     {@link AudioAttributes#USAGE_NOTIFICATION_COMMUNICATION_REQUEST},
-         *     {@link AudioAttributes#USAGE_NOTIFICATION_COMMUNICATION_INSTANT},
-         *     {@link AudioAttributes#USAGE_NOTIFICATION_COMMUNICATION_DELAYED},
-         *     {@link AudioAttributes#USAGE_NOTIFICATION_EVENT},
-         *     {@link AudioAttributes#USAGE_ASSISTANT},
-         *     {@link AudioAttributes#USAGE_ASSISTANCE_ACCESSIBILITY},
-         *     {@link AudioAttributes#USAGE_ASSISTANCE_NAVIGATION_GUIDANCE},
-         *     {@link AudioAttributes#USAGE_ASSISTANCE_SONIFICATION},
-         *     {@link AudioAttributes#USAGE_GAME}.
+         * @param usage one of {@link AttributeSdkUsage#USAGE_UNKNOWN},
+         *     {@link AttributeSdkUsage#USAGE_MEDIA},
+         *     {@link AttributeSdkUsage#USAGE_VOICE_COMMUNICATION},
+         *     {@link AttributeSdkUsage#USAGE_VOICE_COMMUNICATION_SIGNALLING},
+         *     {@link AttributeSdkUsage#USAGE_ALARM}, {@link AudioAttributes#USAGE_NOTIFICATION},
+         *     {@link AttributeSdkUsage#USAGE_NOTIFICATION_RINGTONE},
+         *     {@link AttributeSdkUsage#USAGE_NOTIFICATION_COMMUNICATION_REQUEST},
+         *     {@link AttributeSdkUsage#USAGE_NOTIFICATION_COMMUNICATION_INSTANT},
+         *     {@link AttributeSdkUsage#USAGE_NOTIFICATION_COMMUNICATION_DELAYED},
+         *     {@link AttributeSdkUsage#USAGE_NOTIFICATION_EVENT},
+         *     {@link AttributeSdkUsage#USAGE_ASSISTANT},
+         *     {@link AttributeSdkUsage#USAGE_ASSISTANCE_ACCESSIBILITY},
+         *     {@link AttributeSdkUsage#USAGE_ASSISTANCE_NAVIGATION_GUIDANCE},
+         *     {@link AttributeSdkUsage#USAGE_ASSISTANCE_SONIFICATION},
+         *     {@link AttributeSdkUsage#USAGE_GAME}.
          * @return the same Builder instance.
          */
-        public Builder setUsage(@AttributeUsage int usage) {
+        public Builder setUsage(@AttributeSdkUsage int usage) {
             switch (usage) {
                 case USAGE_UNKNOWN:
                 case USAGE_MEDIA:
@@ -705,7 +773,6 @@
                 case USAGE_GAME:
                 case USAGE_VIRTUAL_SOURCE:
                 case USAGE_ASSISTANT:
-                case USAGE_CALL_ASSISTANT:
                     mUsage = usage;
                     break;
                 default:
@@ -715,6 +782,28 @@
         }
 
         /**
+         * @hide
+         * Sets the attribute describing what is the intended use of the audio signal for categories
+         * of sounds restricted to the system, such as vehicle status or emergency.
+         *
+         * <p>Note that the AudioAttributes have a single usage value, therefore it is illegal to
+         * call both this method and {@link #setUsage(int)}.
+         * @param systemUsage the system-restricted usage.
+         * @return the same Builder instance.
+         */
+        @SystemApi
+        @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+        public @NonNull Builder setSystemUsage(@AttributeSystemUsage int systemUsage) {
+            if (isSystemUsage(systemUsage)) {
+                mSystemUsage = systemUsage;
+            } else {
+                throw new IllegalArgumentException("Invalid system usage " + systemUsage);
+            }
+
+            return this;
+        }
+
+        /**
          * Sets the attribute describing the content type of the audio signal, such as speech,
          * or music.
          * @param contentType the content type values, one of
@@ -1175,6 +1264,14 @@
                 return new String("USAGE_ASSISTANT");
             case USAGE_CALL_ASSISTANT:
                 return new String("USAGE_CALL_ASSISTANT");
+            case USAGE_EMERGENCY:
+                return new String("USAGE_EMERGENCY");
+            case USAGE_SAFETY:
+                return new String("USAGE_SAFETY");
+            case USAGE_VEHICLE_STATUS:
+                return new String("USAGE_VEHICLE_STATUS");
+            case USAGE_ANNOUNCEMENT:
+                return new String("USAGE_ANNOUNCEMENT");
             default:
                 return new String("unknown usage " + usage);
         }
@@ -1221,6 +1318,25 @@
     }
 
     /**
+     * @param usage one of {@link AttributeSystemUsage},
+     *     {@link AttributeSystemUsage#USAGE_CALL_ASSISTANT},
+     *     {@link AttributeSystemUsage#USAGE_EMERGENCY},
+     *     {@link AttributeSystemUsage#USAGE_SAFETY},
+     *     {@link AttributeSystemUsage#USAGE_VEHICLE_STATUS},
+     *     {@link AttributeSystemUsage#USAGE_ANNOUNCEMENT}
+     * @return boolean indicating if the usage is a system usage or not
+     * @hide
+     */
+    @SystemApi
+    public static boolean isSystemUsage(@AttributeSystemUsage int usage) {
+        return (usage == USAGE_CALL_ASSISTANT
+                || usage == USAGE_EMERGENCY
+                || usage == USAGE_SAFETY
+                || usage == USAGE_VEHICLE_STATUS
+                || usage == USAGE_ANNOUNCEMENT);
+    }
+
+    /**
      * Returns the stream type matching this {@code AudioAttributes} instance for volume control.
      * Use this method to derive the stream type needed to configure the volume
      * control slider in an {@link android.app.Activity} with
@@ -1295,6 +1411,10 @@
                 return AudioSystem.STREAM_NOTIFICATION;
             case USAGE_ASSISTANCE_ACCESSIBILITY:
                 return AudioSystem.STREAM_ACCESSIBILITY;
+            case USAGE_EMERGENCY:
+            case USAGE_SAFETY:
+            case USAGE_VEHICLE_STATUS:
+            case USAGE_ANNOUNCEMENT:
             case USAGE_UNKNOWN:
                 return AudioSystem.STREAM_MUSIC;
             default:
@@ -1327,6 +1447,39 @@
 
     /** @hide */
     @IntDef({
+            USAGE_CALL_ASSISTANT,
+            USAGE_EMERGENCY,
+            USAGE_SAFETY,
+            USAGE_VEHICLE_STATUS,
+            USAGE_ANNOUNCEMENT
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface AttributeSystemUsage {}
+
+    /** @hide */
+    @IntDef({
+            USAGE_UNKNOWN,
+            USAGE_MEDIA,
+            USAGE_VOICE_COMMUNICATION,
+            USAGE_VOICE_COMMUNICATION_SIGNALLING,
+            USAGE_ALARM,
+            USAGE_NOTIFICATION,
+            USAGE_NOTIFICATION_RINGTONE,
+            USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
+            USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
+            USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
+            USAGE_NOTIFICATION_EVENT,
+            USAGE_ASSISTANCE_ACCESSIBILITY,
+            USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
+            USAGE_ASSISTANCE_SONIFICATION,
+            USAGE_GAME,
+            USAGE_ASSISTANT,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface AttributeSdkUsage {}
+
+    /** @hide */
+    @IntDef({
         USAGE_UNKNOWN,
         USAGE_MEDIA,
         USAGE_VOICE_COMMUNICATION,
@@ -1344,6 +1497,10 @@
         USAGE_GAME,
         USAGE_ASSISTANT,
         USAGE_CALL_ASSISTANT,
+        USAGE_EMERGENCY,
+        USAGE_SAFETY,
+        USAGE_VEHICLE_STATUS,
+        USAGE_ANNOUNCEMENT,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface AttributeUsage {}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 1b870e8..8ad5c04 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -37,6 +37,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.media.AudioAttributes.AttributeSystemUsage;
 import android.media.audiopolicy.AudioPolicy;
 import android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener;
 import android.media.audiopolicy.AudioProductStrategy;
@@ -1268,6 +1269,39 @@
     }
 
     /**
+     * Set the system usages to be supported on this device.
+     * @param systemUsages array of system usages to support {@link AttributeSystemUsage}
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+    public void setSupportedSystemUsages(@NonNull @AttributeSystemUsage int[] systemUsages) {
+        Objects.requireNonNull(systemUsages, "systemUsages must not be null");
+        final IAudioService service = getService();
+        try {
+            service.setSupportedSystemUsages(systemUsages);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Get the system usages supported on this device.
+     * @return array of supported system usages {@link AttributeSystemUsage}
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+    public @NonNull @AttributeSystemUsage int[] getSupportedSystemUsages() {
+        final IAudioService service = getService();
+        try {
+            return service.getSupportedSystemUsages();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Solo or unsolo a particular stream.
      * <p>
      * Do not use. This method has been deprecated and is now a no-op.
diff --git a/media/java/android/media/AudioMetadata.java b/media/java/android/media/AudioMetadata.java
new file mode 100644
index 0000000..7245aab
--- /dev/null
+++ b/media/java/android/media/AudioMetadata.java
@@ -0,0 +1,406 @@
+/*
+ * 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 android.media;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.Pair;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * AudioMetadata class is used to manage typed key-value pairs for
+ * configuration and capability requests within the Audio Framework.
+ */
+public final class AudioMetadata {
+    /**
+     * Key interface for the map.
+     *
+     * The presence of this {@code Key} interface on an object allows
+     * it to be used to reference metadata in the Audio Framework.
+     *
+     * @param <T> type of value associated with {@code Key}.
+     */
+    // Conceivably metadata keys exposing multiple interfaces
+    // could be eligible to work in multiple framework domains.
+    public interface Key<T> {
+        /**
+         * Returns the internal name of the key.
+         */
+        @NonNull
+        String getName();
+
+        /**
+         * Returns the class type of the associated value.
+         */
+        @NonNull
+        Class<T> getValueClass();
+
+        // TODO: consider adding bool isValid(@NonNull T value)
+
+        /**
+         * Do not allow non-framework apps to create their own keys
+         * by implementing this interface; keep a method hidden.
+         *
+         * @hide
+         */
+        boolean isFromFramework();
+    }
+
+    /**
+     * A read only {@code Map} interface of {@link Key} value pairs.
+     *
+     * Using a {@link Key} interface, look up the corresponding value.
+     */
+    public interface ReadMap {
+        /**
+         * Returns true if the key exists in the map.
+         *
+         * @param key interface for requesting the value.
+         * @param <T> type of value.
+         * @return true if key exists in the Map.
+         */
+        <T> boolean containsKey(@NonNull Key<T> key);
+
+        /**
+         * Returns a copy of the map.
+         *
+         * This is intended for safe conversion between a {@link ReadMap}
+         * interface and a {@link Map} interface.
+         * Currently only simple objects are used for key values which
+         * means a shallow copy is sufficient.
+         *
+         * @return a Map copied from the existing map.
+         */
+        @NonNull
+        Map dup(); // lint checker doesn't like clone().
+
+        /**
+         * Returns the value associated with the key.
+         *
+         * @param key interface for requesting the value.
+         * @param <T> type of value.
+         * @return returns the value of associated with key or null if it doesn't exist.
+         */
+        @Nullable
+        <T> T get(@NonNull Key<T> key);
+
+        /**
+         * Returns a {@code Set} of keys associated with the map.
+         * @hide
+         */
+        @NonNull
+        Set<Key<?>> keySet();
+
+        /**
+         * Returns the number of elements in the map.
+         */
+        int size();
+    }
+
+    /**
+     * A writeable {@link Map} interface of {@link Key} value pairs.
+     * This interface is not guaranteed to be thread-safe
+     * unless the supplier for the {@code Map} states it as thread safe.
+     */
+    // TODO: Create a wrapper like java.util.Collections.synchronizedMap?
+    public interface Map extends ReadMap {
+        /**
+         * Removes the value associated with the key.
+         * @param key interface for storing the value.
+         * @param <T> type of value.
+         * @return the value of the key, null if it doesn't exist.
+         */
+        @Nullable
+        <T> T remove(@NonNull Key<T> key);
+
+        /**
+         * Sets a value for the key.
+         *
+         * @param key interface for storing the value.
+         * @param <T> type of value.
+         * @param value a non-null value of type T.
+         * @return the previous value associated with key or null if it doesn't exist.
+         */
+        // See automatic Kotlin overloading for Java interoperability.
+        // https://kotlinlang.org/docs/reference/java-interop.html#operators
+        // See also Kotlin set for overloaded operator indexing.
+        // https://kotlinlang.org/docs/reference/operator-overloading.html#indexed
+        // Also the Kotlin mutable-list set.
+        // https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-list/set.html
+        @Nullable
+        <T> T set(@NonNull Key<T> key, @NonNull T value);
+    }
+
+    /**
+     * Creates a {@link Map} suitable for adding keys.
+     * @return an empty {@link Map} instance.
+     */
+    @NonNull
+    public static Map createMap() {
+        return new BaseMap();
+    }
+
+    /**
+     * A container class for AudioMetadata Format keys.
+     *
+     * @see AudioTrack.OnCodecFormatChangedListener
+     */
+    public static class Format {
+        // The key name strings used here must match that of the native framework, but are
+        // allowed to change between API releases.  This due to the Java specification
+        // on what is a compile time constant.
+        //
+        // Key<?> are final variables but not constant variables (per Java spec 4.12.4) because
+        // the keys are not a primitive type nor a String initialized by a constant expression.
+        // Hence (per Java spec 13.1.3), they are not resolved at compile time,
+        // rather are picked up by applications at run time.
+        //
+        // So the contractual API behavior of AudioMetadata.Key<> are different than Strings
+        // initialized by a constant expression (for example MediaFormat.KEY_*).
+
+        // See MediaFormat
+        /**
+         * A key representing the bitrate of the encoded stream used in
+         *
+         * If the stream is variable bitrate, this is the average bitrate of the stream.
+         * The unit is bits per second.
+         *
+         * An Integer value.
+         *
+         * @see MediaFormat#KEY_BIT_RATE
+         */
+        @NonNull public static final Key<Integer> KEY_BIT_RATE =
+                createKey("bitrate", Integer.class);
+
+        /**
+         * A key representing the audio channel mask of the stream.
+         *
+         * An Integer value.
+         *
+         * @see AudioTrack#getChannelConfiguration()
+         * @see MediaFormat#KEY_CHANNEL_MASK
+         */
+        @NonNull public static final Key<Integer> KEY_CHANNEL_MASK =
+                createKey("channel-mask", Integer.class);
+
+
+        /**
+         * A key representing the codec mime string.
+         *
+         * A String value.
+         *
+         * @see MediaFormat#KEY_MIME
+         */
+        @NonNull public static final Key<String> KEY_MIME = createKey("mime", String.class);
+
+        /**
+         * A key representing the audio sample rate in Hz of the stream.
+         *
+         * An Integer value.
+         *
+         * @see AudioFormat#getSampleRate()
+         * @see MediaFormat#KEY_SAMPLE_RATE
+         */
+        @NonNull public static final Key<Integer> KEY_SAMPLE_RATE =
+                createKey("sample-rate", Integer.class);
+
+        // Unique to Audio
+
+        /**
+         * A key representing the bit width of an element of decoded data.
+         *
+         * An Integer value.
+         */
+        @NonNull public static final Key<Integer> KEY_BIT_WIDTH =
+                createKey("bit-width", Integer.class);
+
+        /**
+         * A key representing the presence of Atmos in an E-AC3 stream.
+         *
+         * A Boolean value which is true if Atmos is present in an E-AC3 stream.
+         */
+        @NonNull public static final Key<Boolean> KEY_ATMOS_PRESENT =
+                createKey("atmos-present", Boolean.class);
+
+        /**
+         * A key representing the audio encoding used for the stream.
+         * This is the same encoding used in {@link AudioFormat#getEncoding()}.
+         *
+         * An Integer value.
+         *
+         * @see AudioFormat#getEncoding()
+         */
+        @NonNull public static final Key<Integer> KEY_AUDIO_ENCODING =
+                createKey("audio-encoding", Integer.class);
+
+        private Format() {} // delete constructor
+    }
+
+    /////////////////////////////////////////////////////////////////////////
+    // Hidden methods and functions.
+
+    /**
+     * Returns a Key object with the correct interface for the AudioMetadata.
+     *
+     * An interface with the same name and type will be treated as
+     * identical for the purposes of value storage, even though
+     * other methods or hidden parameters may return different values.
+     *
+     * @param name The name of the key.
+     * @param type The class type of the value represented by the key.
+     * @param <T> The type of value.
+     * @return a new key interface.
+     *
+     * Creating keys is currently only allowed by the Framework.
+     * @hide
+     */
+    @NonNull
+    public static <T> Key<T> createKey(String name, Class<T> type) {
+        // Implementation specific.
+        return new Key<T>() {
+            private final String mName = name;
+            private final Class<T> mType = type;
+
+            @Override
+            @NonNull
+            public String getName() {
+                return mName;
+            }
+
+            @Override
+            @NonNull
+            public Class<T> getValueClass() {
+                return mType;
+            }
+
+            // hidden interface method to prevent user class implements the of Key interface.
+            @Override
+            public boolean isFromFramework() {
+                return true;
+            }
+        };
+    }
+
+    /**
+     * @hide
+     *
+     * AudioMetadata is based on interfaces in order to allow multiple inheritance
+     * and maximum flexibility in implementation.
+     *
+     * Here, we provide a simple implementation of {@link Map} interface;
+     * Note that the Keys are not specific to this Map implementation.
+     *
+     * It is possible to require the keys to be of a certain class
+     * before allowing a set or get operation.
+     */
+    public static class BaseMap implements Map {
+        @Override
+        public <T> boolean containsKey(@NonNull Key<T> key) {
+            Pair<Key<?>, Object> valuePair = mHashMap.get(pairFromKey(key));
+            return valuePair != null;
+        }
+
+        @Override
+        @NonNull
+        public Map dup() {
+            BaseMap map = new BaseMap();
+            map.mHashMap.putAll(this.mHashMap);
+            return map;
+        }
+
+        @Override
+        @Nullable
+        public <T> T get(@NonNull Key<T> key) {
+            Pair<Key<?>, Object> valuePair = mHashMap.get(pairFromKey(key));
+            return (T) getValueFromValuePair(valuePair);
+        }
+
+        @Override
+        @NonNull
+        public Set<Key<?>> keySet() {
+            HashSet<Key<?>> set = new HashSet();
+            for (Pair<Key<?>, Object> pair : mHashMap.values()) {
+                set.add(pair.first);
+            }
+            return set;
+        }
+
+        @Override
+        @Nullable
+        public <T> T remove(@NonNull Key<T> key) {
+            Pair<Key<?>, Object> valuePair = mHashMap.remove(pairFromKey(key));
+            return (T) getValueFromValuePair(valuePair);
+        }
+
+        @Override
+        @Nullable
+        public <T> T set(@NonNull Key<T> key, @NonNull T value) {
+            Objects.requireNonNull(value);
+            Pair<Key<?>, Object> valuePair = mHashMap
+                    .put(pairFromKey(key), new Pair<Key<?>, Object>(key, value));
+            return (T) getValueFromValuePair(valuePair);
+        }
+
+        @Override
+        public int size() {
+            return mHashMap.size();
+        }
+
+        /*
+         * Implementation specific.
+         *
+         * To store the value in the HashMap we need to convert the Key interface
+         * to a hashcode() / equals() compliant Pair.
+         */
+        @NonNull
+        private static <T> Pair<String, Class<?>> pairFromKey(@NonNull Key<T> key) {
+            Objects.requireNonNull(key);
+            return new Pair<String, Class<?>>(key.getName(), key.getValueClass());
+        }
+
+        /*
+         * Implementation specific.
+         *
+         * We store in a Pair (valuePair) the key along with the Object value.
+         * This helper returns the Object value from the value pair.
+         */
+        @Nullable
+        private static Object getValueFromValuePair(@Nullable Pair<Key<?>, Object> valuePair) {
+            if (valuePair == null) {
+                return null;
+            }
+            return valuePair.second;
+        }
+
+        /*
+         * Implementation specific.
+         *
+         * We use a HashMap to back the AudioMetadata BaseMap object.
+         * This is not locked, so concurrent reads are permitted if all threads
+         * have a ReadMap; this is risky with a Map.
+         */
+        private final HashMap<Pair<String, Class<?>>, Pair<Key<?>, Object>> mHashMap =
+                new HashMap();
+    }
+
+    // Delete the constructor as there is nothing to implement here.
+    private AudioMetadata() {}
+}
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index fe57e71..48d27fa 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -1174,6 +1174,11 @@
     public static native float getStreamVolumeDB(int stream, int index, int device);
 
     /**
+     * Communicate supported system usages to audio policy service.
+     */
+    public static native int setSupportedSystemUsages(int[] systemUsages);
+
+    /**
      * @see AudioManager#setAllowedCapturePolicy()
      */
     public static native int setAllowedCapturePolicy(int uid, int flags);
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 4dbc79b..f566f64 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -188,6 +188,10 @@
 
     // Events:
     // to keep in sync with frameworks/av/include/media/AudioTrack.h
+    // Note: To avoid collisions with other event constants,
+    // do not define an event here that is the same value as
+    // AudioSystem.NATIVE_EVENT_ROUTING_CHANGE.
+
     /**
      * Event id denotes when playback head has reached a previously set marker.
      */
@@ -210,6 +214,14 @@
      * back (after stop is called) for an offloaded track.
      */
     private static final int NATIVE_EVENT_STREAM_END = 7;
+    /**
+     * Event id denotes when the codec format changes.
+     *
+     * Note: Similar to a device routing change (AudioSystem.NATIVE_EVENT_ROUTING_CHANGE),
+     * this event comes from the AudioFlinger Thread / Output Stream management
+     * (not from buffer indications as above).
+     */
+    private static final int NATIVE_EVENT_CODEC_FORMAT_CHANGE = 100;
 
     private final static String TAG = "android.media.AudioTrack";
 
@@ -3409,6 +3421,67 @@
         }
     }
 
+    //--------------------------------------------------------------------------
+    // Codec notifications
+    //--------------------
+
+    // OnCodecFormatChangedListener notifications uses an instance
+    // of ListenerList to manage its listeners.
+
+    private final Utils.ListenerList<AudioMetadata.ReadMap> mCodecFormatChangedListeners =
+            new Utils.ListenerList();
+
+    /**
+     * Interface definition for a listener for codec format changes.
+     */
+    public interface OnCodecFormatChangedListener {
+        /**
+         * Called when the compressed codec format changes.
+         *
+         * @param audioTrack is the {@code AudioTrack} instance associated with the codec.
+         * @param info is a {@link AudioMetadata.ReadMap} of values which contains decoded format
+         *     changes reported by the codec.  Not all hardware
+         *     codecs indicate codec format changes. Acceptable keys are taken from
+         *     {@code AudioMetadata.Format.KEY_*} range, with the associated value type.
+         */
+        void onCodecFormatChanged(
+                @NonNull AudioTrack audioTrack, @Nullable AudioMetadata.ReadMap info);
+    }
+
+    /**
+     * Adds an {@link OnCodecFormatChangedListener} to receive notifications of
+     * codec format change events on this {@code AudioTrack}.
+     *
+     * @param executor  Specifies the {@link Executor} object to control execution.
+     *
+     * @param listener The {@link OnCodecFormatChangedListener} interface to receive
+     *     notifications of codec events.
+     */
+    public void addOnCodecFormatChangedListener(
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull OnCodecFormatChangedListener listener) { // NPE checks done by ListenerList.
+        mCodecFormatChangedListeners.add(
+                listener, /* key for removal */
+                executor,
+                (int eventCode, AudioMetadata.ReadMap readMap) -> {
+                    // eventCode is unused by this implementation.
+                    listener.onCodecFormatChanged(this, readMap);
+                }
+        );
+    }
+
+    /**
+     * Removes an {@link OnCodecFormatChangedListener} which has been previously added
+     * to receive codec format change events.
+     *
+     * @param listener The previously added {@link OnCodecFormatChangedListener} interface
+     * to remove.
+     */
+    public void removeOnCodecFormatChangedListener(
+            @NonNull OnCodecFormatChangedListener listener) {
+        mCodecFormatChangedListeners.remove(listener);  // NPE checks done by ListenerList.
+    }
+
     //---------------------------------------------------------
     // Interface definitions
     //--------------------
@@ -3745,6 +3818,12 @@
             return;
         }
 
+        if (what == NATIVE_EVENT_CODEC_FORMAT_CHANGE) {
+            track.mCodecFormatChangedListeners.notify(
+                    0 /* eventCode, unused */, (AudioMetadata.ReadMap) obj);
+            return;
+        }
+
         if (what == NATIVE_EVENT_CAN_WRITE_MORE_DATA
                 || what == NATIVE_EVENT_NEW_IAUDIOTRACK
                 || what == NATIVE_EVENT_STREAM_END) {
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 8e8385d..7f1c692 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -105,6 +105,10 @@
 
     int getLastAudibleStreamVolume(int streamType);
 
+    void setSupportedSystemUsages(in int[] systemUsages);
+
+    int[] getSupportedSystemUsages();
+
     List<AudioProductStrategy> getAudioProductStrategies();
 
     boolean isMicrophoneMuted();
diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java
index 9908e04..6689080 100644
--- a/media/java/android/media/MediaFile.java
+++ b/media/java/android/media/MediaFile.java
@@ -200,6 +200,84 @@
         return null;
     }
 
+    /**
+     * Check whether the mime type is document or not.
+     * @param mimeType the mime type to check
+     * @return true, if the mimeType is matched. Otherwise, false.
+     */
+    public static boolean isDocumentMimeType(@Nullable String mimeType) {
+        if (mimeType == null) {
+            return false;
+        }
+
+        final String normalizedMimeType = normalizeMimeType(mimeType);
+        if (normalizedMimeType.startsWith("text/")) {
+            return true;
+        }
+
+        switch (normalizedMimeType) {
+            case "application/epub+zip":
+            case "application/msword":
+            case "application/pdf":
+            case "application/rtf":
+            case "application/vnd.ms-excel":
+            case "application/vnd.ms-excel.addin.macroEnabled.12":
+            case "application/vnd.ms-excel.sheet.binary.macroEnabled.12":
+            case "application/vnd.ms-excel.sheet.macroEnabled.12":
+            case "application/vnd.ms-excel.template.macroEnabled.12":
+            case "application/vnd.ms-powerpoint":
+            case "application/vnd.ms-powerpoint.addin.macroEnabled.12":
+            case "application/vnd.ms-powerpoint.presentation.macroEnabled.12":
+            case "application/vnd.ms-powerpoint.slideshow.macroEnabled.12":
+            case "application/vnd.ms-powerpoint.template.macroEnabled.12":
+            case "application/vnd.ms-word.document.macroEnabled.12":
+            case "application/vnd.ms-word.template.macroEnabled.12":
+            case "application/vnd.oasis.opendocument.chart":
+            case "application/vnd.oasis.opendocument.database":
+            case "application/vnd.oasis.opendocument.formula":
+            case "application/vnd.oasis.opendocument.graphics":
+            case "application/vnd.oasis.opendocument.graphics-template":
+            case "application/vnd.oasis.opendocument.presentation":
+            case "application/vnd.oasis.opendocument.presentation-template":
+            case "application/vnd.oasis.opendocument.spreadsheet":
+            case "application/vnd.oasis.opendocument.spreadsheet-template":
+            case "application/vnd.oasis.opendocument.text":
+            case "application/vnd.oasis.opendocument.text-master":
+            case "application/vnd.oasis.opendocument.text-template":
+            case "application/vnd.oasis.opendocument.text-web":
+            case "application/vnd.openxmlformats-officedocument.presentationml.presentation":
+            case "application/vnd.openxmlformats-officedocument.presentationml.slideshow":
+            case "application/vnd.openxmlformats-officedocument.presentationml.template":
+            case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":
+            case "application/vnd.openxmlformats-officedocument.spreadsheetml.template":
+            case "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
+            case "application/vnd.openxmlformats-officedocument.wordprocessingml.template":
+            case "application/vnd.stardivision.calc":
+            case "application/vnd.stardivision.chart":
+            case "application/vnd.stardivision.draw":
+            case "application/vnd.stardivision.impress":
+            case "application/vnd.stardivision.impress-packed":
+            case "application/vnd.stardivision.mail":
+            case "application/vnd.stardivision.math":
+            case "application/vnd.stardivision.writer":
+            case "application/vnd.stardivision.writer-global":
+            case "application/vnd.sun.xml.calc":
+            case "application/vnd.sun.xml.calc.template":
+            case "application/vnd.sun.xml.draw":
+            case "application/vnd.sun.xml.draw.template":
+            case "application/vnd.sun.xml.impress":
+            case "application/vnd.sun.xml.impress.template":
+            case "application/vnd.sun.xml.math":
+            case "application/vnd.sun.xml.writer":
+            case "application/vnd.sun.xml.writer.global":
+            case "application/vnd.sun.xml.writer.template":
+            case "application/x-mspublisher":
+                return true;
+            default:
+                return false;
+        }
+    }
+
     public static boolean isExifMimeType(@Nullable String mimeType) {
         // For simplicity, assume that all image files might have EXIF data
         return isImageMimeType(mimeType);
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 71c97534..2d820e7 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -632,7 +632,6 @@
     private boolean mScreenOnWhilePlaying;
     private boolean mStayAwake;
     private int mStreamType = AudioManager.USE_DEFAULT_STREAM_TYPE;
-    private int mUsage = -1;
 
     // Modular DRM
     private UUID mDrmUUID;
@@ -2220,7 +2219,6 @@
             throw new IllegalArgumentException(msg);
         }
         baseUpdateAudioAttributes(attributes);
-        mUsage = attributes.getUsage();
         Parcel pattributes = Parcel.obtain();
         attributes.writeToParcel(pattributes, AudioAttributes.FLATTEN_TAGS);
         setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES, pattributes);
diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java
index 5cb32d6..61e2f77 100644
--- a/media/java/android/media/MediaRouter2Manager.java
+++ b/media/java/android/media/MediaRouter2Manager.java
@@ -178,8 +178,9 @@
 
     /**
      * Gets routing controllers of an application with the given package name.
-     * If the application isn't running or it doesn't use {@link MediaRouter2}, an empty list
-     * will be returned.
+     * The first element of the returned list is the system routing controller.
+     *
+     * @see MediaRouter2#getSystemController()
      */
     @NonNull
     public List<RoutingController> getRoutingControllers(@NonNull String packageName) {
@@ -188,7 +189,8 @@
         List<RoutingController> controllers = new ArrayList<>();
 
         for (RoutingSessionInfo sessionInfo : getActiveSessions()) {
-            if (TextUtils.equals(sessionInfo.getClientPackageName(), packageName)) {
+            if (sessionInfo.isSystemSession()
+                    || TextUtils.equals(sessionInfo.getClientPackageName(), packageName)) {
                 controllers.add(new RoutingController(sessionInfo));
             }
         }
@@ -196,8 +198,11 @@
     }
 
     /**
-     * Gets the list of all active routing sessions. It doesn't include default routing sessions
-     * of applications.
+     * Gets the list of all active routing sessions.
+     * The first element of the list is the system routing session containing
+     * phone speakers, wired headset, Bluetooth devices.
+     * The system routing session is shared by apps such that controlling it will affect
+     * all apps.
      */
     @NonNull
     public List<RoutingSessionInfo> getActiveSessions() {
diff --git a/media/java/android/media/Utils.java b/media/java/android/media/Utils.java
index d942bb6..7a4e7b8 100644
--- a/media/java/android/media/Utils.java
+++ b/media/java/android/media/Utils.java
@@ -16,12 +16,17 @@
 
 package android.media;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.TestApi;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.Binder;
 import android.os.Environment;
 import android.os.FileUtils;
+import android.os.Handler;
 import android.provider.OpenableColumns;
 import android.util.Log;
 import android.util.Pair;
@@ -29,14 +34,26 @@
 import android.util.Rational;
 import android.util.Size;
 
+import com.android.internal.annotations.GuardedBy;
+
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.util.Arrays;
 import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Objects;
 import java.util.Vector;
+import java.util.concurrent.Executor;
 
-// package private
-class Utils {
+/**
+ * Media Utilities
+ *
+ * This class is hidden but public to allow CTS testing and verification
+ * of the static methods and classes.
+ *
+ * @hide
+ */
+public class Utils {
     private static final String TAG = "Utils";
 
     /**
@@ -381,4 +398,265 @@
         // it already represents the file's name.
         return uri.toString();
     }
+
+    /**
+     * {@code ListenerList} is a helper class that delivers events to listeners.
+     *
+     * It is written to isolate the <strong>mechanics</strong> of event delivery from the
+     * <strong>details</strong> of those events.
+     *
+     * The {@code ListenerList} is parameterized on the generic type {@code V}
+     * of the object delivered by {@code notify()}.
+     * This gives compile time type safety over run-time casting of a general {@code Object},
+     * much like {@code HashMap&lt;String, Object&gt;} does not give type safety of the
+     * stored {@code Object} value and may allow
+     * permissive storage of {@code Object}s that are not expected by users of the
+     * {@code HashMap}, later resulting in run-time cast exceptions that
+     * could have been caught by replacing
+     * {@code Object} with a more precise type to enforce a compile time contract.
+     *
+     * The {@code ListenerList} is implemented as a single method callback
+     * - or a "listener" according to Android style guidelines.
+     *
+     * The {@code ListenerList} can be trivially extended by a suitable lambda to implement
+     * a <strong> multiple method abstract class</strong> "callback",
+     * in which the generic type {@code V} could be an {@code Object}
+     * to encapsulate the details of the parameters of each callback method, and
+     * {@code instanceof} could be used to disambiguate which callback method to use.
+     * A {@link Bundle} could alternatively encapsulate those generic parameters,
+     * perhaps more conveniently.
+     * Again, this is a detail of the event, not the mechanics of the event delivery,
+     * which this class is concerned with.
+     *
+     * For details on how to use this class to implement a <strong>single listener</strong>
+     * {@code ListenerList}, see notes on {@link #add}.
+     *
+     * For details on how to optimize this class to implement
+     * a listener based on {@link Handler}s
+     * instead of {@link Executor}s, see{@link #ListenerList(boolean, boolean, boolean)}.
+     *
+     * This is a TestApi for CTS Unit Testing, not exposed for general Application use.
+     * @hide
+     *
+     * @param <V> The class of the object returned to the listener.
+     */
+    @TestApi
+    public static class ListenerList<V> {
+        /**
+         * The Listener interface for callback.
+         *
+         * @param <V> The class of the object returned to the listener
+         */
+        public interface Listener<V> {
+            /**
+             * General event listener interface which is managed by the {@code ListenerList}.
+             *
+             * @param eventCode is an integer representing the event type. This is an
+             *     implementation defined parameter.
+             * @param info is the object returned to the listener.  It is expected
+             *     that the listener makes a private copy of the {@code info} object before
+             *     modification, as it is the same instance passed to all listeners.
+             *     This is an implementation defined parameter that may be null.
+             */
+            void onEvent(int eventCode, @Nullable V info);
+        }
+
+        private interface ListenerWithCancellation<V> extends Listener<V> {
+            void cancel();
+        }
+
+        /**
+         * Default {@code ListenerList} constructor for {@link Executor} based implementation.
+         *
+         * TODO: consider adding a "name" for debugging if this is used for
+         * multiple listener implementations.
+         */
+        public ListenerList() {
+            this(true /* restrictSingleCallerOnEvent */,
+                true /* clearCallingIdentity */,
+                false /* forceRemoveConsistency*/);
+        }
+
+        /**
+         * Specific {@code ListenerList} constructor for customization.
+         *
+         * See the internal notes for the corresponding private variables on the behavior of
+         * the boolean configuration parameters.
+         *
+         * {@code ListenerList(true, true, false)} is the default and used for
+         * {@link Executor} based notification implementation.
+         *
+         * {@code ListenerList(false, false, false)} may be used for as an optimization
+         * where the {@link Executor} is actually a {@link Handler} post.
+         *
+         * @param restrictSingleCallerOnEvent whether the listener will only be called by
+         *     a single thread at a time.
+         * @param clearCallingIdentity whether the binder calling identity on
+         *     {@link #notify} is cleared.
+         * @param forceRemoveConsistency whether remove() guarantees no more callbacks to
+         *     the listener immediately after the call.
+         */
+        public ListenerList(boolean restrictSingleCallerOnEvent,
+                boolean clearCallingIdentity,
+                boolean forceRemoveConsistency) {
+            mRestrictSingleCallerOnEvent = restrictSingleCallerOnEvent;
+            mClearCallingIdentity = clearCallingIdentity;
+            mForceRemoveConsistency = forceRemoveConsistency;
+        }
+
+        /**
+         * Adds a listener to the {@code ListenerList}.
+         *
+         * The {@code ListenerList} is most often used to hold {@code multiple} listeners.
+         *
+         * Per Android style, for a single method Listener interface, the add and remove
+         * would be wrapped in "addSomeListener" or "removeSomeListener";
+         * or a lambda implemented abstract class callback, wrapped in
+         * "registerSomeCallback" or "unregisterSomeCallback".
+         *
+         * We allow a general {@code key} to be attached to add and remove that specific
+         * listener.  It could be the {@code listener} object itself.
+         *
+         * For some implementations, there may be only a {@code single} listener permitted.
+         *
+         * Per Android style, for a single listener {@code ListenerList},
+         * the naming of the wrapping call to {@link #add} would be
+         * "setSomeListener" with a nullable listener, which would be null
+         * to call {@link #remove}.
+         *
+         * In that case, the caller may use this {@link #add} with a single constant object for
+         * the {@code key} to enforce only one Listener in the {@code ListenerList}.
+         * Likewise on remove it would use that
+         * same single constant object to remove the listener.
+         * That {@code key} object could be the {@code ListenerList} itself for convenience.
+         *
+         * @param key is a unique object that is used to identify the listener
+         *     when {@code remove()} is called. It can be the listener itself.
+         * @param executor is used to execute the callback.
+         * @param listener is the {@link AudioTrack.ListenerList.Listener}
+         *     interface to be called upon {@link notify}.
+         */
+        public void add(
+                @NonNull Object key, @NonNull Executor executor, @NonNull Listener<V> listener) {
+            Objects.requireNonNull(key);
+            Objects.requireNonNull(executor);
+            Objects.requireNonNull(listener);
+
+            // construct wrapper outside of lock.
+            ListenerWithCancellation<V> listenerWithCancellation =
+                    new ListenerWithCancellation<V>() {
+                        private final Object mLock = new Object(); // our lock is per Listener.
+                        private volatile boolean mCancelled = false; // atomic rmw not needed.
+
+                        @Override
+                        public void onEvent(int eventCode, V info) {
+                            executor.execute(() -> {
+                                // Note deep execution of locking and cancellation
+                                // so this works after posting on different threads.
+                                if (mRestrictSingleCallerOnEvent || mForceRemoveConsistency) {
+                                    synchronized (mLock) {
+                                        if (mCancelled) return;
+                                        listener.onEvent(eventCode, info);
+                                    }
+                                } else {
+                                    if (mCancelled) return;
+                                    listener.onEvent(eventCode, info);
+                                }
+                            });
+                        }
+
+                        @Override
+                        public void cancel() {
+                            if (mForceRemoveConsistency) {
+                                synchronized (mLock) {
+                                    mCancelled = true;
+                                }
+                            } else {
+                                mCancelled = true;
+                            }
+                        }
+                    };
+
+            synchronized (mListeners) {
+                // TODO: consider an option to check the existence of the key
+                // and throw an ISE if it exists.
+                mListeners.put(key, listenerWithCancellation);  // replaces old value
+            }
+        }
+
+        /**
+         * Removes a listener from the {@code ListenerList}.
+         *
+         * @param key the unique object associated with the listener during {@link #add}.
+         */
+        public void remove(@NonNull Object key) {
+            Objects.requireNonNull(key);
+
+            ListenerWithCancellation<V> listener;
+            synchronized (mListeners) {
+                listener = mListeners.get(key);
+                if (listener == null) { // TODO: consider an option to throw ISE Here.
+                    return;
+                }
+                mListeners.remove(key);  // removes if exist
+            }
+
+            // cancel outside of lock
+            listener.cancel();
+        }
+
+        /**
+         * Notifies all listeners on the List.
+         *
+         * @param eventCode to pass to all listeners.
+         * @param info to pass to all listeners. This is an implemention defined parameter
+         *     which may be {@code null}.
+         */
+        public void notify(int eventCode, @Nullable V info) {
+            Object[] listeners; // note we can't cast an object array to a listener array
+            synchronized (mListeners) {
+                if (mListeners.size() == 0) {
+                    return;
+                }
+                listeners = mListeners.values().toArray(); // guarantees a copy.
+            }
+
+            // notify outside of lock.
+            final Long identity = mClearCallingIdentity ? Binder.clearCallingIdentity() : null;
+            try {
+                for (Object object : listeners) {
+                    final ListenerWithCancellation<V> listener =
+                            (ListenerWithCancellation<V>) object;
+                    listener.onEvent(eventCode, info);
+                }
+            } finally {
+                if (identity != null) {
+                    Binder.restoreCallingIdentity(identity);
+                }
+            }
+        }
+
+        @GuardedBy("mListeners")
+        private HashMap<Object, ListenerWithCancellation<V>> mListeners = new HashMap<>();
+
+        // An Executor may run in multiple threads, whereas a Handler runs on a single Looper.
+        // Should be true for an Executor to avoid concurrent calling into the same listener,
+        // can be false for a Handler as a Handler forces single thread caller for each listener.
+        private final boolean mRestrictSingleCallerOnEvent; // default true
+
+        // An Executor may run in the calling thread, whereas a handler will post to the Looper.
+        // Should be true for an Executor to prevent privilege escalation,
+        // can be false for a Handler as its thread is not the calling binder thread.
+        private final boolean mClearCallingIdentity; // default true
+
+        // Guaranteeing no listener callbacks after removal requires taking the same lock for the
+        // remove as the callback; this is a reversal in calling layers,
+        // hence the risk of lock order inversion is great.
+        //
+        // Set to true only if you can control the caller's listen and remove methods and/or
+        // the threading of the Executor used for each listener.
+        // When set to false, we do not lock, but still do a best effort to cancel messages
+        // on the fly.
+        private final boolean mForceRemoveConsistency; // default false
+    }
 }
diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
index b5e9d1b..c199c6f 100644
--- a/media/java/android/media/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -95,7 +95,7 @@
     // For TV input hardware binding
     List<TvInputHardwareInfo> getHardwareList();
     ITvInputHardware acquireTvInputHardware(int deviceId, in ITvInputHardwareCallback callback,
-            in TvInputInfo info, int userId);
+            in TvInputInfo info, int userId, String tvInputSessionId, int priorityHint);
     void releaseTvInputHardware(int deviceId, in ITvInputHardware hardware, int userId);
 
     // For TV input capturing
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index fc5d67d..9cdfa2a 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -1735,8 +1735,14 @@
     /**
      * Acquires {@link Hardware} object for the given device ID.
      *
-     * <p>A subsequent call to this method on the same {@code deviceId} will release the currently
-     * acquired Hardware.
+     * <p>A subsequent call to this method on the same {@code deviceId} could release the currently
+     * acquired Hardware if TunerResourceManager(TRM) detects higher priority from the current
+     * request.
+     *
+     * <p>If the client would like to provide information for the TRM to compare, use
+     * {@link #acquireTvInputHardware(int, TvInputInfo, HardwareCallback, String, int)} instead.
+     *
+     * <p>Otherwise default priority will be applied.
      *
      * @param deviceId The device ID to acquire Hardware for.
      * @param callback A callback to receive updates on Hardware.
@@ -1747,8 +1753,49 @@
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE)
-    public Hardware acquireTvInputHardware(int deviceId, TvInputInfo info,
-            final HardwareCallback callback) {
+    public Hardware acquireTvInputHardware(int deviceId, @NonNull TvInputInfo info,
+            @NonNull final HardwareCallback callback) {
+        Preconditions.checkNotNull(info);
+        Preconditions.checkNotNull(callback);
+        return acquireTvInputHardwareInternal(deviceId, info, callback, null,
+                TvInputService.PRIORITY_HINT_USE_CASE_TYPE_LIVE);
+    }
+
+    /**
+     * Acquires {@link Hardware} object for the given device ID.
+     *
+     * <p>A subsequent call to this method on the same {@code deviceId} could release the currently
+     * acquired Hardware if TunerResourceManager(TRM) detects higher priority from the current
+     * request.
+     *
+     * @param deviceId The device ID to acquire Hardware for.
+     * @param callback A callback to receive updates on Hardware.
+     * @param info The TV input which will use the acquired Hardware.
+     * @param tvInputSessionId a String returned to TIS when the session was created.
+     *        {@see TvInputService#onCreateSession(String, String)}. If null, the client will be
+     *        treated as a background app.
+     * @param priorityHint The use case of the client. {@see TvInputService#PriorityHintUseCaseType}
+     * @return Hardware on success, {@code null} otherwise. When the TRM decides to not grant
+     *         resource, null is returned and the {@link IllegalStateException} is thrown with
+     *         "No enough resources".
+     *
+     * @hide
+     */
+    @SystemApi
+    @Nullable
+    @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE)
+    public Hardware acquireTvInputHardware(int deviceId, @NonNull TvInputInfo info,
+            @NonNull final HardwareCallback callback,
+            @Nullable String tvInputSessionId,
+            @TvInputService.PriorityHintUseCaseType int priorityHint) {
+        Preconditions.checkNotNull(info);
+        Preconditions.checkNotNull(callback);
+        return acquireTvInputHardwareInternal(deviceId, info, callback,
+                tvInputSessionId, priorityHint);
+    }
+
+    private Hardware acquireTvInputHardwareInternal(int deviceId, TvInputInfo info,
+             final HardwareCallback callback, String tvInputSessionId, int priorityHint) {
         try {
             return new Hardware(
                     mService.acquireTvInputHardware(deviceId, new ITvInputHardwareCallback.Stub() {
@@ -1761,7 +1808,7 @@
                 public void onStreamConfigChanged(TvStreamConfig[] configs) {
                     callback.onStreamConfigChanged(configs);
                 }
-            }, info, mUserId));
+                    }, info, mUserId, tvInputSessionId, priorityHint));
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 62ab2c9..bac425b 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -23,6 +23,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.content.Context;
+import android.media.tv.TvInputService;
 import android.media.tv.tuner.TunerConstants.Result;
 import android.media.tv.tuner.dvr.DvrPlayback;
 import android.media.tv.tuner.dvr.DvrRecorder;
@@ -55,7 +56,7 @@
  * @hide
  */
 @SystemApi
-public final class Tuner implements AutoCloseable  {
+public class Tuner implements AutoCloseable  {
     private static final String TAG = "MediaTvTuner";
     private static final boolean DEBUG = false;
 
@@ -88,25 +89,13 @@
     /**
      * Constructs a Tuner instance.
      *
-     * @param context context of the caller.
-     */
-    public Tuner(@NonNull Context context) {
-        mContext = context;
-        nativeSetup();
-    }
-
-    /**
-     * Constructs a Tuner instance.
-     *
      * @param context the context of the caller.
      * @param tvInputSessionId the session ID of the TV input.
      * @param useCase the use case of this Tuner instance.
-     *
-     * @hide
-     * TODO: replace the other constructor
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
-    public Tuner(@NonNull Context context, @NonNull String tvInputSessionId, int useCase,
+    public Tuner(@NonNull Context context, @NonNull String tvInputSessionId,
+            @TvInputService.PriorityHintUseCaseType int useCase,
             @Nullable OnResourceLostListener listener) {
         mContext = context;
     }
@@ -115,18 +104,21 @@
      * Shares the frontend resource with another Tuner instance
      *
      * @param tuner the Tuner instance to share frontend resource with.
-     *
-     * @hide
      */
     public void shareFrontendFromTuner(@NonNull Tuner tuner) {
+        // TODO: implementation.
     }
 
 
     private long mNativeContext; // used by native jMediaTuner
 
-    /** @hide */
+    /**
+     * Releases the Tuner instance.
+     */
     @Override
-    public void close() {}
+    public void close() {
+        // TODO: implementation.
+    }
 
     /**
      * Native Initialization.
@@ -176,7 +168,7 @@
     /**
      * Listener for resource lost.
      *
-     * @hide
+     * <p>Resource is reclaimed and tuner instance is forced to close.
      */
     public interface OnResourceLostListener {
         /**
@@ -269,8 +261,8 @@
      * start a new tuning.
      *
      * <p>
-     * Tune is an async call, with {@link OnTuneEventListener#LOCKED LOCKED} and {@link
-     * OnTuneEventListener#NO_SIGNAL NO_SIGNAL} events sent to the {@link OnTuneEventListener}
+     * Tune is an async call, with {@link OnTuneEventListener#SIGNAL_LOCKED} and {@link
+     * OnTuneEventListener#SIGNAL_NO_SIGNAL} events sent to the {@link OnTuneEventListener}
      * specified in {@link #setOnTuneEventListener(Executor, OnTuneEventListener)}.
      *
      * @param settings Signal delivery information the frontend uses to
@@ -357,13 +349,9 @@
      * @param lnb the LNB instance.
      *
      * @return result status of the operation.
-     *
-     * @hide
      */
-    @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
     @Result
-    public int setLnb(@NonNull Lnb lnb) {
-        TunerUtils.checkTunerPermission(mContext);
+    private int setLnb(@NonNull Lnb lnb) {
         return nativeSetLnb(lnb.mId);
     }
 
@@ -373,8 +361,6 @@
      * @param enable {@code true} to activate LNA module; {@code false} to deactivate LNA.
      *
      * @return result status of the operation.
-     *
-     * @hide
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
     @Result
@@ -390,10 +376,9 @@
      *
      * @param statusTypes an array of status types which the caller requests.
      * @return statuses which response the caller's requests.
-     * @hide
      */
     @Nullable
-    public FrontendStatus getFrontendStatus(int[] statusTypes) {
+    public FrontendStatus getFrontendStatus(@NonNull int[] statusTypes) {
         return nativeGetFrontendStatus(statusTypes);
     }
 
@@ -402,8 +387,6 @@
      *
      * @param filter the filter instance for the hardware sync ID.
      * @return the id of hardware A/V sync.
-     *
-     * @hide
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
     public int getAvSyncHwId(@NonNull Filter filter) {
@@ -419,8 +402,6 @@
      *
      * @param avSyncHwId the hardware id of A/V sync.
      * @return the current timestamp of hardware A/V sync.
-     *
-     * @hide
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
     public long getAvSyncTime(int avSyncHwId) {
@@ -436,8 +417,6 @@
      *
      * @param ciCamId specify CI-CAM Id to connect.
      * @return result status of the operation.
-     *
-     * @hide
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
     @Result
@@ -452,8 +431,6 @@
      * <p>The demux will use the output from the frontend as the input after this call.
      *
      * @return result status of the operation.
-     *
-     * @hide
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
     @Result
@@ -466,8 +443,6 @@
      * Gets the frontend information.
      *
      * @return The frontend information. {@code null} if the operation failed.
-     *
-     * @hide
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
     @Nullable
@@ -480,23 +455,7 @@
     }
 
     /**
-     * Gets the frontend ID.
-     *
-     * @hide
-     */
-    @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
-    public int getFrontendId() {
-        TunerUtils.checkTunerPermission(mContext);
-        if (mFrontend == null) {
-            throw new IllegalStateException("frontend is not initialized");
-        }
-        return mFrontend.mId;
-    }
-
-    /**
      * Gets Demux capabilities.
-     *
-     * @hide
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
     @Nullable
@@ -622,19 +581,6 @@
     }
 
     /**
-     * This class is used to interact with descramblers.
-     *
-     * <p> Descrambler is a hardware component used to descramble data.
-     *
-     * <p> This class controls the TIS interaction with Tuner HAL.
-     * TODO: Remove
-     */
-    public class Descrambler {
-        private Descrambler() {
-        }
-    }
-
-    /**
      * Opens a Descrambler in tuner.
      *
      * @return  a {@link Descrambler} object.
diff --git a/media/java/android/media/tv/tuner/TunerConstants.java b/media/java/android/media/tv/tuner/TunerConstants.java
index c030619..f54808d 100644
--- a/media/java/android/media/tv/tuner/TunerConstants.java
+++ b/media/java/android/media/tv/tuner/TunerConstants.java
@@ -17,14 +17,8 @@
 package android.media.tv.tuner;
 
 import android.annotation.IntDef;
-import android.annotation.LongDef;
 import android.annotation.SystemApi;
 import android.hardware.tv.tuner.V1_0.Constants;
-import android.media.tv.tuner.frontend.DvbcFrontendSettings;
-import android.media.tv.tuner.frontend.DvbsFrontendSettings;
-import android.media.tv.tuner.frontend.Isdbs3FrontendSettings;
-import android.media.tv.tuner.frontend.IsdbsFrontendSettings;
-import android.media.tv.tuner.frontend.IsdbtFrontendSettings;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -38,12 +32,10 @@
 public final class TunerConstants {
     /**
      * Invalid TS packet ID.
-     * @hide
      */
     public static final int INVALID_TS_PID = Constants.Constant.INVALID_TS_PID;
     /**
      * Invalid stream ID.
-     * @hide
      */
     public static final int INVALID_STREAM_ID = Constants.Constant.INVALID_STREAM_ID;
 
@@ -58,7 +50,7 @@
     /**
      * Scan type auto.
      *
-     * <p> Tuner will send {@link #onLocked}
+     * <p> Tuner will send {@link android.media.tv.tuner.frontend.ScanCallback#onLocked}
      */
     public static final int SCAN_TYPE_AUTO = Constants.FrontendScanType.SCAN_AUTO;
     /**
@@ -70,350 +62,6 @@
     public static final int SCAN_TYPE_BLIND = Constants.FrontendScanType.SCAN_BLIND;
 
     /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = "INDEX_TYPE_", value =
-            {INDEX_TYPE_NONE, INDEX_TYPE_SC, INDEX_TYPE_SC_HEVC})
-    public @interface ScIndexType {}
-
-    /**
-     * Start Code Index is not used.
-     * @hide
-     */
-    public static final int INDEX_TYPE_NONE = Constants.DemuxRecordScIndexType.NONE;
-    /**
-     * Start Code index.
-     * @hide
-     */
-    public static final int INDEX_TYPE_SC = Constants.DemuxRecordScIndexType.SC;
-    /**
-     * Start Code index for HEVC.
-     * @hide
-     */
-    public static final int INDEX_TYPE_SC_HEVC = Constants.DemuxRecordScIndexType.SC_HEVC;
-
-    /**
-     * Indexes can be tagged by Start Code in PES (Packetized Elementary Stream)
-     * according to ISO/IEC 13818-1.
-     * @hide
-     */
-    @IntDef(flag = true, value = {SC_INDEX_I_FRAME, SC_INDEX_P_FRAME, SC_INDEX_B_FRAME,
-            SC_INDEX_SEQUENCE})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface ScIndex {}
-
-    /**
-     * SC index for a new I-frame.
-     */
-    public static final int SC_INDEX_I_FRAME = Constants.DemuxScIndex.I_FRAME;
-    /**
-     * SC index for a new P-frame.
-     */
-    public static final int SC_INDEX_P_FRAME = Constants.DemuxScIndex.P_FRAME;
-    /**
-     * SC index for a new B-frame.
-     */
-    public static final int SC_INDEX_B_FRAME = Constants.DemuxScIndex.B_FRAME;
-    /**
-     * SC index for a new sequence.
-     */
-    public static final int SC_INDEX_SEQUENCE = Constants.DemuxScIndex.SEQUENCE;
-
-
-    /**
-     * Indexes can be tagged by NAL unit group in HEVC according to ISO/IEC 23008-2.
-     *
-     * @hide
-     */
-    @IntDef(flag = true,
-            value = {SC_HEVC_INDEX_SPS, SC_HEVC_INDEX_AUD, SC_HEVC_INDEX_SLICE_CE_BLA_W_LP,
-            SC_HEVC_INDEX_SLICE_BLA_W_RADL, SC_HEVC_INDEX_SLICE_BLA_N_LP,
-            SC_HEVC_INDEX_SLICE_IDR_W_RADL, SC_HEVC_INDEX_SLICE_IDR_N_LP,
-            SC_HEVC_INDEX_SLICE_TRAIL_CRA})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface ScHevcIndex {}
-
-    /**
-     * SC HEVC index SPS.
-     */
-    public static final int SC_HEVC_INDEX_SPS = Constants.DemuxScHevcIndex.SPS;
-    /**
-     * SC HEVC index AUD.
-     */
-    public static final int SC_HEVC_INDEX_AUD = Constants.DemuxScHevcIndex.AUD;
-    /**
-     * SC HEVC index SLICE_CE_BLA_W_LP.
-     */
-    public static final int SC_HEVC_INDEX_SLICE_CE_BLA_W_LP =
-            Constants.DemuxScHevcIndex.SLICE_CE_BLA_W_LP;
-    /**
-     * SC HEVC index SLICE_BLA_W_RADL.
-     */
-    public static final int SC_HEVC_INDEX_SLICE_BLA_W_RADL =
-            Constants.DemuxScHevcIndex.SLICE_BLA_W_RADL;
-    /**
-     * SC HEVC index SLICE_BLA_N_LP.
-     */
-    public static final int SC_HEVC_INDEX_SLICE_BLA_N_LP =
-            Constants.DemuxScHevcIndex.SLICE_BLA_N_LP;
-    /**
-     * SC HEVC index SLICE_IDR_W_RADL.
-     */
-    public static final int SC_HEVC_INDEX_SLICE_IDR_W_RADL =
-            Constants.DemuxScHevcIndex.SLICE_IDR_W_RADL;
-    /**
-     * SC HEVC index SLICE_IDR_N_LP.
-     */
-    public static final int SC_HEVC_INDEX_SLICE_IDR_N_LP =
-            Constants.DemuxScHevcIndex.SLICE_IDR_N_LP;
-    /**
-     * SC HEVC index SLICE_TRAIL_CRA.
-     */
-    public static final int SC_HEVC_INDEX_SLICE_TRAIL_CRA =
-            Constants.DemuxScHevcIndex.SLICE_TRAIL_CRA;
-
-    /** @hide */
-    @LongDef({FEC_UNDEFINED, FEC_AUTO, FEC_1_2, FEC_1_3, FEC_1_4, FEC_1_5, FEC_2_3, FEC_2_5,
-            FEC_2_9, FEC_3_4, FEC_3_5, FEC_4_5, FEC_4_15, FEC_5_6, FEC_5_9, FEC_6_7, FEC_7_8,
-            FEC_7_9, FEC_7_15, FEC_8_9, FEC_8_15, FEC_9_10, FEC_9_20, FEC_11_15, FEC_11_20,
-            FEC_11_45, FEC_13_18, FEC_13_45, FEC_14_45, FEC_23_36, FEC_25_36, FEC_26_45, FEC_28_45,
-            FEC_29_45, FEC_31_45, FEC_32_45, FEC_77_90})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface FrontendInnerFec {}
-
-    /**
-     * FEC not defined
-     * @hide
-     */
-    public static final long FEC_UNDEFINED = Constants.FrontendInnerFec.FEC_UNDEFINED;
-    /**
-     * hardware is able to detect and set FEC automatically
-     * @hide
-     */
-    public static final long FEC_AUTO = Constants.FrontendInnerFec.AUTO;
-    /**
-     * 1/2 conv. code rate
-     * @hide
-     */
-    public static final long FEC_1_2 = Constants.FrontendInnerFec.FEC_1_2;
-    /**
-     * 1/3 conv. code rate
-     * @hide
-     */
-    public static final long FEC_1_3 = Constants.FrontendInnerFec.FEC_1_3;
-    /**
-     * 1/4 conv. code rate
-     * @hide
-     */
-    public static final long FEC_1_4 = Constants.FrontendInnerFec.FEC_1_4;
-    /**
-     * 1/5 conv. code rate
-     * @hide
-     */
-    public static final long FEC_1_5 = Constants.FrontendInnerFec.FEC_1_5;
-    /**
-     * 2/3 conv. code rate
-     * @hide
-     */
-    public static final long FEC_2_3 = Constants.FrontendInnerFec.FEC_2_3;
-    /**
-     * 2/5 conv. code rate
-     * @hide
-     */
-    public static final long FEC_2_5 = Constants.FrontendInnerFec.FEC_2_5;
-    /**
-     * 2/9 conv. code rate
-     * @hide
-     */
-    public static final long FEC_2_9 = Constants.FrontendInnerFec.FEC_2_9;
-    /**
-     * 3/4 conv. code rate
-     * @hide
-     */
-    public static final long FEC_3_4 = Constants.FrontendInnerFec.FEC_3_4;
-    /**
-     * 3/5 conv. code rate
-     * @hide
-     */
-    public static final long FEC_3_5 = Constants.FrontendInnerFec.FEC_3_5;
-    /**
-     * 4/5 conv. code rate
-     * @hide
-     */
-    public static final long FEC_4_5 = Constants.FrontendInnerFec.FEC_4_5;
-    /**
-     * 4/15 conv. code rate
-     * @hide
-     */
-    public static final long FEC_4_15 = Constants.FrontendInnerFec.FEC_4_15;
-    /**
-     * 5/6 conv. code rate
-     * @hide
-     */
-    public static final long FEC_5_6 = Constants.FrontendInnerFec.FEC_5_6;
-    /**
-     * 5/9 conv. code rate
-     * @hide
-     */
-    public static final long FEC_5_9 = Constants.FrontendInnerFec.FEC_5_9;
-    /**
-     * 6/7 conv. code rate
-     * @hide
-     */
-    public static final long FEC_6_7 = Constants.FrontendInnerFec.FEC_6_7;
-    /**
-     * 7/8 conv. code rate
-     * @hide
-     */
-    public static final long FEC_7_8 = Constants.FrontendInnerFec.FEC_7_8;
-    /**
-     * 7/9 conv. code rate
-     * @hide
-     */
-    public static final long FEC_7_9 = Constants.FrontendInnerFec.FEC_7_9;
-    /**
-     * 7/15 conv. code rate
-     * @hide
-     */
-    public static final long FEC_7_15 = Constants.FrontendInnerFec.FEC_7_15;
-    /**
-     * 8/9 conv. code rate
-     * @hide
-     */
-    public static final long FEC_8_9 = Constants.FrontendInnerFec.FEC_8_9;
-    /**
-     * 8/15 conv. code rate
-     * @hide
-     */
-    public static final long FEC_8_15 = Constants.FrontendInnerFec.FEC_8_15;
-    /**
-     * 9/10 conv. code rate
-     * @hide
-     */
-    public static final long FEC_9_10 = Constants.FrontendInnerFec.FEC_9_10;
-    /**
-     * 9/20 conv. code rate
-     * @hide
-     */
-    public static final long FEC_9_20 = Constants.FrontendInnerFec.FEC_9_20;
-    /**
-     * 11/15 conv. code rate
-     * @hide
-     */
-    public static final long FEC_11_15 = Constants.FrontendInnerFec.FEC_11_15;
-    /**
-     * 11/20 conv. code rate
-     * @hide
-     */
-    public static final long FEC_11_20 = Constants.FrontendInnerFec.FEC_11_20;
-    /**
-     * 11/45 conv. code rate
-     * @hide
-     */
-    public static final long FEC_11_45 = Constants.FrontendInnerFec.FEC_11_45;
-    /**
-     * 13/18 conv. code rate
-     * @hide
-     */
-    public static final long FEC_13_18 = Constants.FrontendInnerFec.FEC_13_18;
-    /**
-     * 13/45 conv. code rate
-     * @hide
-     */
-    public static final long FEC_13_45 = Constants.FrontendInnerFec.FEC_13_45;
-    /**
-     * 14/45 conv. code rate
-     * @hide
-     */
-    public static final long FEC_14_45 = Constants.FrontendInnerFec.FEC_14_45;
-    /**
-     * 23/36 conv. code rate
-     * @hide
-     */
-    public static final long FEC_23_36 = Constants.FrontendInnerFec.FEC_23_36;
-    /**
-     * 25/36 conv. code rate
-     * @hide
-     */
-    public static final long FEC_25_36 = Constants.FrontendInnerFec.FEC_25_36;
-    /**
-     * 26/45 conv. code rate
-     * @hide
-     */
-    public static final long FEC_26_45 = Constants.FrontendInnerFec.FEC_26_45;
-    /**
-     * 28/45 conv. code rate
-     * @hide
-     */
-    public static final long FEC_28_45 = Constants.FrontendInnerFec.FEC_28_45;
-    /**
-     * 29/45 conv. code rate
-     * @hide
-     */
-    public static final long FEC_29_45 = Constants.FrontendInnerFec.FEC_29_45;
-    /**
-     * 31/45 conv. code rate
-     * @hide
-     */
-    public static final long FEC_31_45 = Constants.FrontendInnerFec.FEC_31_45;
-    /**
-     * 32/45 conv. code rate
-     * @hide
-     */
-    public static final long FEC_32_45 = Constants.FrontendInnerFec.FEC_32_45;
-    /**
-     * 77/90 conv. code rate
-     * @hide
-     */
-    public static final long FEC_77_90 = Constants.FrontendInnerFec.FEC_77_90;
-
-
-    /** @hide */
-    @IntDef(value = {
-            DvbcFrontendSettings.MODULATION_UNDEFINED,
-            DvbcFrontendSettings.MODULATION_AUTO,
-            DvbcFrontendSettings.MODULATION_MOD_16QAM,
-            DvbcFrontendSettings.MODULATION_MOD_32QAM,
-            DvbcFrontendSettings.MODULATION_MOD_64QAM,
-            DvbcFrontendSettings.MODULATION_MOD_128QAM,
-            DvbcFrontendSettings.MODULATION_MOD_256QAM,
-            DvbsFrontendSettings.MODULATION_UNDEFINED,
-            DvbsFrontendSettings.MODULATION_AUTO,
-            DvbsFrontendSettings.MODULATION_MOD_QPSK,
-            DvbsFrontendSettings.MODULATION_MOD_8PSK,
-            DvbsFrontendSettings.MODULATION_MOD_16QAM,
-            DvbsFrontendSettings.MODULATION_MOD_16PSK,
-            DvbsFrontendSettings.MODULATION_MOD_32PSK,
-            DvbsFrontendSettings.MODULATION_MOD_ACM,
-            DvbsFrontendSettings.MODULATION_MOD_8APSK,
-            DvbsFrontendSettings.MODULATION_MOD_16APSK,
-            DvbsFrontendSettings.MODULATION_MOD_32APSK,
-            DvbsFrontendSettings.MODULATION_MOD_64APSK,
-            DvbsFrontendSettings.MODULATION_MOD_128APSK,
-            DvbsFrontendSettings.MODULATION_MOD_256APSK,
-            DvbsFrontendSettings.MODULATION_MOD_RESERVED,
-            IsdbsFrontendSettings.MODULATION_UNDEFINED,
-            IsdbsFrontendSettings.MODULATION_AUTO,
-            IsdbsFrontendSettings.MODULATION_MOD_BPSK,
-            IsdbsFrontendSettings.MODULATION_MOD_QPSK,
-            IsdbsFrontendSettings.MODULATION_MOD_TC8PSK,
-            Isdbs3FrontendSettings.MODULATION_UNDEFINED,
-            Isdbs3FrontendSettings.MODULATION_AUTO,
-            Isdbs3FrontendSettings.MODULATION_MOD_BPSK,
-            Isdbs3FrontendSettings.MODULATION_MOD_QPSK,
-            Isdbs3FrontendSettings.MODULATION_MOD_8PSK,
-            Isdbs3FrontendSettings.MODULATION_MOD_16APSK,
-            Isdbs3FrontendSettings.MODULATION_MOD_32APSK,
-            IsdbtFrontendSettings.MODULATION_UNDEFINED,
-            IsdbtFrontendSettings.MODULATION_AUTO,
-            IsdbtFrontendSettings.MODULATION_MOD_DQPSK,
-            IsdbtFrontendSettings.MODULATION_MOD_QPSK,
-            IsdbtFrontendSettings.MODULATION_MOD_16QAM,
-            IsdbtFrontendSettings.MODULATION_MOD_64QAM})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface FrontendModulation {}
-
-
-    /** @hide */
     @IntDef({RESULT_SUCCESS, RESULT_UNAVAILABLE, RESULT_NOT_INITIALIZED, RESULT_INVALID_STATE,
             RESULT_INVALID_ARGUMENT, RESULT_OUT_OF_MEMORY, RESULT_UNKNOWN_ERROR})
     @Retention(RetentionPolicy.SOURCE)
diff --git a/media/java/android/media/tv/tuner/filter/RecordSettings.java b/media/java/android/media/tv/tuner/filter/RecordSettings.java
index 209ed67..0c812ab 100644
--- a/media/java/android/media/tv/tuner/filter/RecordSettings.java
+++ b/media/java/android/media/tv/tuner/filter/RecordSettings.java
@@ -22,8 +22,6 @@
 import android.annotation.SystemApi;
 import android.content.Context;
 import android.hardware.tv.tuner.V1_0.Constants;
-import android.media.tv.tuner.TunerConstants;
-import android.media.tv.tuner.TunerConstants.ScIndexType;
 import android.media.tv.tuner.TunerUtils;
 
 import java.lang.annotation.Retention;
@@ -112,29 +110,130 @@
      */
     public static final int TS_INDEX_ADAPTATION_EXTENSION_FLAG =
             Constants.DemuxTsIndex.ADAPTATION_EXTENSION_FLAG;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = "INDEX_TYPE_", value =
+            {INDEX_TYPE_NONE, INDEX_TYPE_SC, INDEX_TYPE_SC_HEVC})
+    public @interface ScIndexType {}
+
+    /**
+     * Start Code Index is not used.
+     */
+    public static final int INDEX_TYPE_NONE = Constants.DemuxRecordScIndexType.NONE;
+    /**
+     * Start Code index.
+     */
+    public static final int INDEX_TYPE_SC = Constants.DemuxRecordScIndexType.SC;
+    /**
+     * Start Code index for HEVC.
+     */
+    public static final int INDEX_TYPE_SC_HEVC = Constants.DemuxRecordScIndexType.SC_HEVC;
+
+    /**
+     * Indexes can be tagged by Start Code in PES (Packetized Elementary Stream)
+     * according to ISO/IEC 13818-1.
+     * @hide
+     */
+    @IntDef(flag = true, value = {SC_INDEX_I_FRAME, SC_INDEX_P_FRAME, SC_INDEX_B_FRAME,
+            SC_INDEX_SEQUENCE})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ScIndex {}
+
+    /**
+     * SC index for a new I-frame.
+     */
+    public static final int SC_INDEX_I_FRAME = Constants.DemuxScIndex.I_FRAME;
+    /**
+     * SC index for a new P-frame.
+     */
+    public static final int SC_INDEX_P_FRAME = Constants.DemuxScIndex.P_FRAME;
+    /**
+     * SC index for a new B-frame.
+     */
+    public static final int SC_INDEX_B_FRAME = Constants.DemuxScIndex.B_FRAME;
+    /**
+     * SC index for a new sequence.
+     */
+    public static final int SC_INDEX_SEQUENCE = Constants.DemuxScIndex.SEQUENCE;
+
+
+    /**
+     * Indexes can be tagged by NAL unit group in HEVC according to ISO/IEC 23008-2.
+     *
+     * @hide
+     */
+    @IntDef(flag = true,
+            value = {SC_HEVC_INDEX_SPS, SC_HEVC_INDEX_AUD, SC_HEVC_INDEX_SLICE_CE_BLA_W_LP,
+            SC_HEVC_INDEX_SLICE_BLA_W_RADL, SC_HEVC_INDEX_SLICE_BLA_N_LP,
+            SC_HEVC_INDEX_SLICE_IDR_W_RADL, SC_HEVC_INDEX_SLICE_IDR_N_LP,
+            SC_HEVC_INDEX_SLICE_TRAIL_CRA})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ScHevcIndex {}
+
+    /**
+     * SC HEVC index SPS.
+     */
+    public static final int SC_HEVC_INDEX_SPS = Constants.DemuxScHevcIndex.SPS;
+    /**
+     * SC HEVC index AUD.
+     */
+    public static final int SC_HEVC_INDEX_AUD = Constants.DemuxScHevcIndex.AUD;
+    /**
+     * SC HEVC index SLICE_CE_BLA_W_LP.
+     */
+    public static final int SC_HEVC_INDEX_SLICE_CE_BLA_W_LP =
+            Constants.DemuxScHevcIndex.SLICE_CE_BLA_W_LP;
+    /**
+     * SC HEVC index SLICE_BLA_W_RADL.
+     */
+    public static final int SC_HEVC_INDEX_SLICE_BLA_W_RADL =
+            Constants.DemuxScHevcIndex.SLICE_BLA_W_RADL;
+    /**
+     * SC HEVC index SLICE_BLA_N_LP.
+     */
+    public static final int SC_HEVC_INDEX_SLICE_BLA_N_LP =
+            Constants.DemuxScHevcIndex.SLICE_BLA_N_LP;
+    /**
+     * SC HEVC index SLICE_IDR_W_RADL.
+     */
+    public static final int SC_HEVC_INDEX_SLICE_IDR_W_RADL =
+            Constants.DemuxScHevcIndex.SLICE_IDR_W_RADL;
+    /**
+     * SC HEVC index SLICE_IDR_N_LP.
+     */
+    public static final int SC_HEVC_INDEX_SLICE_IDR_N_LP =
+            Constants.DemuxScHevcIndex.SLICE_IDR_N_LP;
+    /**
+     * SC HEVC index SLICE_TRAIL_CRA.
+     */
+    public static final int SC_HEVC_INDEX_SLICE_TRAIL_CRA =
+            Constants.DemuxScHevcIndex.SLICE_TRAIL_CRA;
+
     /**
      * @hide
      */
     @IntDef(flag = true,
             prefix = "SC_",
             value = {
-                TunerConstants.SC_INDEX_I_FRAME,
-                TunerConstants.SC_INDEX_P_FRAME,
-                TunerConstants.SC_INDEX_B_FRAME,
-                TunerConstants.SC_INDEX_SEQUENCE,
-                TunerConstants.SC_HEVC_INDEX_SPS,
-                TunerConstants.SC_HEVC_INDEX_AUD,
-                TunerConstants.SC_HEVC_INDEX_SLICE_CE_BLA_W_LP,
-                TunerConstants.SC_HEVC_INDEX_SLICE_BLA_W_RADL,
-                TunerConstants.SC_HEVC_INDEX_SLICE_BLA_N_LP,
-                TunerConstants.SC_HEVC_INDEX_SLICE_IDR_W_RADL,
-                TunerConstants.SC_HEVC_INDEX_SLICE_IDR_N_LP,
-                TunerConstants.SC_HEVC_INDEX_SLICE_TRAIL_CRA,
+                SC_INDEX_I_FRAME,
+                SC_INDEX_P_FRAME,
+                SC_INDEX_B_FRAME,
+                SC_INDEX_SEQUENCE,
+                SC_HEVC_INDEX_SPS,
+                SC_HEVC_INDEX_AUD,
+                SC_HEVC_INDEX_SLICE_CE_BLA_W_LP,
+                SC_HEVC_INDEX_SLICE_BLA_W_RADL,
+                SC_HEVC_INDEX_SLICE_BLA_N_LP,
+                SC_HEVC_INDEX_SLICE_IDR_W_RADL,
+                SC_HEVC_INDEX_SLICE_IDR_N_LP,
+                SC_HEVC_INDEX_SLICE_TRAIL_CRA,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ScIndexMask {}
 
 
+
     private final int mTsIndexMask;
     private final int mScIndexType;
     private final int mScIndexMask;
diff --git a/media/java/android/media/tv/tuner/frontend/AnalogFrontendCapabilities.java b/media/java/android/media/tv/tuner/frontend/AnalogFrontendCapabilities.java
index aa64df5..096bc67 100644
--- a/media/java/android/media/tv/tuner/frontend/AnalogFrontendCapabilities.java
+++ b/media/java/android/media/tv/tuner/frontend/AnalogFrontendCapabilities.java
@@ -16,11 +16,14 @@
 
 package android.media.tv.tuner.frontend;
 
+import android.annotation.SystemApi;
+
 /**
  * Capabilities for analog tuners.
  *
  * @hide
  */
+@SystemApi
 public class AnalogFrontendCapabilities extends FrontendCapabilities {
     @AnalogFrontendSettings.SignalType
     private final int mTypeCap;
diff --git a/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java
index 61880ab..7b85fa8 100644
--- a/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java
@@ -195,7 +195,7 @@
     /**
      * Creates a builder for {@link AnalogFrontendSettings}.
      *
-     * @param the context of the caller.
+     * @param context the context of the caller.
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
     @NonNull
@@ -223,7 +223,7 @@
          * Sets analog signal type.
          */
         @NonNull
-        public Builder setASignalType(@SignalType int signalType) {
+        public Builder setSignalType(@SignalType int signalType) {
             mSignalType = signalType;
             return this;
         }
diff --git a/media/java/android/media/tv/tuner/frontend/Atsc3FrontendCapabilities.java b/media/java/android/media/tv/tuner/frontend/Atsc3FrontendCapabilities.java
index 1fd1f63..7730912 100644
--- a/media/java/android/media/tv/tuner/frontend/Atsc3FrontendCapabilities.java
+++ b/media/java/android/media/tv/tuner/frontend/Atsc3FrontendCapabilities.java
@@ -16,10 +16,14 @@
 
 package android.media.tv.tuner.frontend;
 
+import android.annotation.SystemApi;
+
 /**
  * ATSC-3 Capabilities.
+ *
  * @hide
  */
+@SystemApi
 public class Atsc3FrontendCapabilities extends FrontendCapabilities {
     private final int mBandwidthCap;
     private final int mModulationCap;
@@ -63,7 +67,7 @@
      * Gets code rate capability.
      */
     @Atsc3FrontendSettings.CodeRate
-    public int getCodeRateCapability() {
+    public int getPlpCodeRateCapability() {
         return mCodeRateCap;
     }
     /**
diff --git a/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java b/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java
index 5e1ba72..85f3f72 100644
--- a/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.content.Context;
 import android.hardware.tv.tuner.V1_0.Constants;
 import android.media.tv.tuner.TunerUtils;
@@ -28,8 +29,10 @@
 
 /**
  * Frontend settings for ATSC-3.
+ *
  * @hide
  */
+@SystemApi
 public class Atsc3FrontendSettings extends FrontendSettings {
 
     /** @hide */
@@ -273,9 +276,9 @@
     public static final int DEMOD_OUTPUT_FORMAT_BASEBAND_PACKET =
             Constants.FrontendAtsc3DemodOutputFormat.BASEBAND_PACKET;
 
-    public final int mBandwidth;
-    public final int mDemodOutputFormat;
-    public final Atsc3PlpSettings[] mPlpSettings;
+    private final int mBandwidth;
+    private final int mDemodOutputFormat;
+    private final Atsc3PlpSettings[] mPlpSettings;
 
     private Atsc3FrontendSettings(int frequency, int bandwidth, int demodOutputFormat,
             Atsc3PlpSettings[] plpSettings) {
@@ -302,6 +305,7 @@
     /**
      * Gets PLP Settings.
      */
+    @NonNull
     public Atsc3PlpSettings[] getPlpSettings() {
         return mPlpSettings;
     }
@@ -349,7 +353,7 @@
          * Sets PLP Settings.
          */
         @NonNull
-        public Builder setPlpSettings(Atsc3PlpSettings[] plpSettings) {
+        public Builder setPlpSettings(@NonNull Atsc3PlpSettings[] plpSettings) {
             mPlpSettings = plpSettings;
             return this;
         }
diff --git a/media/java/android/media/tv/tuner/frontend/Atsc3PlpSettings.java b/media/java/android/media/tv/tuner/frontend/Atsc3PlpSettings.java
index 43a68a0..fe61dbc 100644
--- a/media/java/android/media/tv/tuner/frontend/Atsc3PlpSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/Atsc3PlpSettings.java
@@ -18,13 +18,16 @@
 
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.content.Context;
 import android.media.tv.tuner.TunerUtils;
 
 /**
- * PLP settings for ATSC-3.
+ * Physical Layer Pipe (PLP) settings for ATSC-3.
+ *
  * @hide
  */
+@SystemApi
 public class Atsc3PlpSettings {
     private final int mPlpId;
     private final int mModulation;
diff --git a/media/java/android/media/tv/tuner/frontend/AtscFrontendCapabilities.java b/media/java/android/media/tv/tuner/frontend/AtscFrontendCapabilities.java
index 0ff516d..eb21caa 100644
--- a/media/java/android/media/tv/tuner/frontend/AtscFrontendCapabilities.java
+++ b/media/java/android/media/tv/tuner/frontend/AtscFrontendCapabilities.java
@@ -16,10 +16,14 @@
 
 package android.media.tv.tuner.frontend;
 
+import android.annotation.SystemApi;
+
 /**
  * ATSC Capabilities.
+ *
  * @hide
  */
+@SystemApi
 public class AtscFrontendCapabilities extends FrontendCapabilities {
     private final int mModulationCap;
 
diff --git a/media/java/android/media/tv/tuner/frontend/AtscFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/AtscFrontendSettings.java
index 32901d8..fc82a1c 100644
--- a/media/java/android/media/tv/tuner/frontend/AtscFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/AtscFrontendSettings.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.content.Context;
 import android.hardware.tv.tuner.V1_0.Constants;
 import android.media.tv.tuner.TunerUtils;
@@ -28,8 +29,10 @@
 
 /**
  * Frontend settings for ATSC.
+ *
  * @hide
  */
+@SystemApi
 public class AtscFrontendSettings extends FrontendSettings {
 
     /** @hide */
diff --git a/media/java/android/media/tv/tuner/frontend/DvbcFrontendCapabilities.java b/media/java/android/media/tv/tuner/frontend/DvbcFrontendCapabilities.java
index f3fbdb5..faa5434 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbcFrontendCapabilities.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbcFrontendCapabilities.java
@@ -16,12 +16,14 @@
 
 package android.media.tv.tuner.frontend;
 
-import android.media.tv.tuner.TunerConstants.FrontendInnerFec;
+import android.annotation.SystemApi;
 
 /**
  * DVBC Capabilities.
+ *
  * @hide
  */
+@SystemApi
 public class DvbcFrontendCapabilities extends FrontendCapabilities {
     private final int mModulationCap;
     private final int mFecCap;
@@ -43,7 +45,7 @@
     /**
      * Gets inner FEC capability.
      */
-    @FrontendInnerFec
+    @FrontendSettings.InnerFec
     public int getFecCapability() {
         return mFecCap;
     }
diff --git a/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java
index 3d212d3..bfa4f3f 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java
@@ -19,9 +19,9 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.content.Context;
 import android.hardware.tv.tuner.V1_0.Constants;
-import android.media.tv.tuner.TunerConstants.FrontendInnerFec;
 import android.media.tv.tuner.TunerUtils;
 
 import java.lang.annotation.Retention;
@@ -29,8 +29,10 @@
 
 /**
  * Frontend settings for DVBC.
+ *
  * @hide
  */
+@SystemApi
 public class DvbcFrontendSettings extends FrontendSettings {
 
     /** @hide */
@@ -169,7 +171,7 @@
     /**
      * Gets Inner Forward Error Correction.
      */
-    @FrontendInnerFec
+    @InnerFec
     public long getFec() {
         return mFec;
     }
@@ -239,7 +241,7 @@
          * Sets Inner Forward Error Correction.
          */
         @NonNull
-        public Builder setFec(@FrontendInnerFec long fec) {
+        public Builder setFec(@InnerFec long fec) {
             mFec = fec;
             return this;
         }
diff --git a/media/java/android/media/tv/tuner/frontend/DvbsCodeRate.java b/media/java/android/media/tv/tuner/frontend/DvbsCodeRate.java
index 04d3375..2bdd379 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbsCodeRate.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbsCodeRate.java
@@ -18,22 +18,24 @@
 
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.content.Context;
-import android.media.tv.tuner.TunerConstants.FrontendInnerFec;
 import android.media.tv.tuner.TunerUtils;
 
 /**
  * Code rate for DVBS.
+ *
  * @hide
  */
+@SystemApi
 public class DvbsCodeRate {
-    private final long mFec;
+    private final long mInnerFec;
     private final boolean mIsLinear;
     private final boolean mIsShortFrames;
     private final int mBitsPer1000Symbol;
 
     private DvbsCodeRate(long fec, boolean isLinear, boolean isShortFrames, int bitsPer1000Symbol) {
-        mFec = fec;
+        mInnerFec = fec;
         mIsLinear = isLinear;
         mIsShortFrames = isShortFrames;
         mBitsPer1000Symbol = bitsPer1000Symbol;
@@ -42,9 +44,9 @@
     /**
      * Gets inner FEC.
      */
-    @FrontendInnerFec
-    public long getFec() {
-        return mFec;
+    @FrontendSettings.InnerFec
+    public long getInnerFec() {
+        return mInnerFec;
     }
     /**
      * Checks whether it's linear.
@@ -93,7 +95,7 @@
          * Sets inner FEC.
          */
         @NonNull
-        public Builder setFec(@FrontendInnerFec long fec) {
+        public Builder setInnerFec(@FrontendSettings.InnerFec long fec) {
             mFec = fec;
             return this;
         }
diff --git a/media/java/android/media/tv/tuner/frontend/DvbsFrontendCapabilities.java b/media/java/android/media/tv/tuner/frontend/DvbsFrontendCapabilities.java
index bd615d0..1e25cf2 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbsFrontendCapabilities.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbsFrontendCapabilities.java
@@ -16,12 +16,14 @@
 
 package android.media.tv.tuner.frontend;
 
-import android.media.tv.tuner.TunerConstants.FrontendInnerFec;
+import android.annotation.SystemApi;
 
 /**
  * DVBS Capabilities.
+ *
  * @hide
  */
+@SystemApi
 public class DvbsFrontendCapabilities extends FrontendCapabilities {
     private final int mModulationCap;
     private final long mInnerFecCap;
@@ -43,7 +45,7 @@
     /**
      * Gets inner FEC capability.
      */
-    @FrontendInnerFec
+    @FrontendSettings.InnerFec
     public long getInnerFecCapability() {
         return mInnerFecCap;
     }
diff --git a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
index 44dbcc0..4a4fed5 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.content.Context;
 import android.hardware.tv.tuner.V1_0.Constants;
 import android.media.tv.tuner.TunerUtils;
@@ -29,8 +30,10 @@
 
 /**
  * Frontend settings for DVBS.
+ *
  * @hide
  */
+@SystemApi
 public class DvbsFrontendSettings extends FrontendSettings {
     /** @hide */
     @IntDef(flag = true,
@@ -209,7 +212,7 @@
 
 
     private final int mModulation;
-    private final DvbsCodeRate mCoderate;
+    private final DvbsCodeRate mCodeRate;
     private final int mSymbolRate;
     private final int mRolloff;
     private final int mPilot;
@@ -217,11 +220,11 @@
     private final int mStandard;
     private final int mVcmMode;
 
-    private DvbsFrontendSettings(int frequency, int modulation, DvbsCodeRate coderate,
+    private DvbsFrontendSettings(int frequency, int modulation, DvbsCodeRate codeRate,
             int symbolRate, int rolloff, int pilot, int inputStreamId, int standard, int vcm) {
         super(frequency);
         mModulation = modulation;
-        mCoderate = coderate;
+        mCodeRate = codeRate;
         mSymbolRate = symbolRate;
         mRolloff = rolloff;
         mPilot = pilot;
@@ -241,8 +244,8 @@
      * Gets Code rate.
      */
     @Nullable
-    public DvbsCodeRate getCoderate() {
-        return mCoderate;
+    public DvbsCodeRate getCodeRate() {
+        return mCodeRate;
     }
     /**
      * Gets Symbol Rate in symbols per second.
@@ -302,7 +305,7 @@
      */
     public static class Builder extends FrontendSettings.Builder<Builder> {
         private int mModulation;
-        private DvbsCodeRate mCoderate;
+        private DvbsCodeRate mCodeRate;
         private int mSymbolRate;
         private int mRolloff;
         private int mPilot;
@@ -325,8 +328,8 @@
          * Sets Code rate.
          */
         @NonNull
-        public Builder setCoderate(@Nullable DvbsCodeRate coderate) {
-            mCoderate = coderate;
+        public Builder setCodeRate(@Nullable DvbsCodeRate codeRate) {
+            mCodeRate = codeRate;
             return this;
         }
         /**
@@ -383,7 +386,7 @@
          */
         @NonNull
         public DvbsFrontendSettings build() {
-            return new DvbsFrontendSettings(mFrequency, mModulation, mCoderate, mSymbolRate,
+            return new DvbsFrontendSettings(mFrequency, mModulation, mCodeRate, mSymbolRate,
                     mRolloff, mPilot, mInputStreamId, mStandard, mVcmMode);
         }
 
diff --git a/media/java/android/media/tv/tuner/frontend/DvbtFrontendCapabilities.java b/media/java/android/media/tv/tuner/frontend/DvbtFrontendCapabilities.java
index 0d47179..524952d 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbtFrontendCapabilities.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbtFrontendCapabilities.java
@@ -16,27 +16,31 @@
 
 package android.media.tv.tuner.frontend;
 
+import android.annotation.SystemApi;
+
 /**
  * DVBT Capabilities.
+ *
  * @hide
  */
+@SystemApi
 public class DvbtFrontendCapabilities extends FrontendCapabilities {
     private final int mTransmissionModeCap;
     private final int mBandwidthCap;
     private final int mConstellationCap;
-    private final int mCoderateCap;
+    private final int mCodeRateCap;
     private final int mHierarchyCap;
     private final int mGuardIntervalCap;
     private final boolean mIsT2Supported;
     private final boolean mIsMisoSupported;
 
     private DvbtFrontendCapabilities(int transmissionModeCap, int bandwidthCap,
-            int constellationCap, int coderateCap, int hierarchyCap, int guardIntervalCap,
+            int constellationCap, int codeRateCap, int hierarchyCap, int guardIntervalCap,
             boolean isT2Supported, boolean isMisoSupported) {
         mTransmissionModeCap = transmissionModeCap;
         mBandwidthCap = bandwidthCap;
         mConstellationCap = constellationCap;
-        mCoderateCap = coderateCap;
+        mCodeRateCap = codeRateCap;
         mHierarchyCap = hierarchyCap;
         mGuardIntervalCap = guardIntervalCap;
         mIsT2Supported = isT2Supported;
@@ -67,9 +71,9 @@
     /**
      * Gets code rate capability.
      */
-    @DvbtFrontendSettings.Coderate
+    @DvbtFrontendSettings.CodeRate
     public int getCodeRateCapability() {
-        return mCoderateCap;
+        return mCodeRateCap;
     }
     /**
      * Gets hierarchy capability.
diff --git a/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java
index 9a82de0..e99fd36f 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.content.Context;
 import android.hardware.tv.tuner.V1_0.Constants;
 import android.media.tv.tuner.TunerUtils;
@@ -28,8 +29,10 @@
 
 /**
  * Frontend settings for DVBT.
+ *
  * @hide
  */
+@SystemApi
 public class DvbtFrontendSettings extends FrontendSettings {
 
     /** @hide */
@@ -220,7 +223,7 @@
             value = {CODERATE_UNDEFINED, CODERATE_AUTO, CODERATE_1_2, CODERATE_2_3, CODERATE_3_4,
             CODERATE_5_6, CODERATE_7_8, CODERATE_3_5, CODERATE_4_5, CODERATE_6_7, CODERATE_8_9})
     @Retention(RetentionPolicy.SOURCE)
-    public @interface Coderate {}
+    public @interface CodeRate {}
 
     /**
      * Code rate undefined.
@@ -347,8 +350,7 @@
     public static final int STANDARD_T2 = Constants.FrontendDvbtStandard.T2;
 
     /** @hide */
-    @IntDef(flag = true,
-            prefix = "PLP_MODE_",
+    @IntDef(prefix = "PLP_MODE_",
             value = {PLP_MODE_UNDEFINED, PLP_MODE_AUTO, PLP_MODE_MANUAL})
     @Retention(RetentionPolicy.SOURCE)
     public @interface PlpMode {}
@@ -371,8 +373,8 @@
     private final int mBandwidth;
     private final int mConstellation;
     private final int mHierarchy;
-    private final int mHpCoderate;
-    private final int mLpCoderate;
+    private final int mHpCodeRate;
+    private final int mLpCodeRate;
     private final int mGuardInterval;
     private final boolean mIsHighPriority;
     private final int mStandard;
@@ -382,7 +384,7 @@
     private final int mPlpGroupId;
 
     private DvbtFrontendSettings(int frequency, int transmissionMode, int bandwidth,
-            int constellation, int hierarchy, int hpCoderate, int lpCoderate, int guardInterval,
+            int constellation, int hierarchy, int hpCodeRate, int lpCodeRate, int guardInterval,
             boolean isHighPriority, int standard, boolean isMiso, int plpMode, int plpId,
             int plpGroupId) {
         super(frequency);
@@ -390,8 +392,8 @@
         mBandwidth = bandwidth;
         mConstellation = constellation;
         mHierarchy = hierarchy;
-        mHpCoderate = hpCoderate;
-        mLpCoderate = lpCoderate;
+        mHpCodeRate = hpCodeRate;
+        mLpCodeRate = lpCodeRate;
         mGuardInterval = guardInterval;
         mIsHighPriority = isHighPriority;
         mStandard = standard;
@@ -432,16 +434,16 @@
     /**
      * Gets Code Rate for High Priority level.
      */
-    @Coderate
-    public int getHpCoderate() {
-        return mHpCoderate;
+    @CodeRate
+    public int getHpCodeRate() {
+        return mHpCodeRate;
     }
     /**
      * Gets Code Rate for Low Priority level.
      */
-    @Coderate
-    public int getLpCoderate() {
-        return mLpCoderate;
+    @CodeRate
+    public int getLpCodeRate() {
+        return mLpCodeRate;
     }
     /**
      * Gets Guard Interval.
@@ -509,8 +511,8 @@
         private int mBandwidth;
         private int mConstellation;
         private int mHierarchy;
-        private int mHpCoderate;
-        private int mLpCoderate;
+        private int mHpCodeRate;
+        private int mLpCodeRate;
         private int mGuardInterval;
         private boolean mIsHighPriority;
         private int mStandard;
@@ -558,16 +560,16 @@
          * Sets Code Rate for High Priority level.
          */
         @NonNull
-        public Builder setHpCoderate(@Coderate int hpCoderate) {
-            mHpCoderate = hpCoderate;
+        public Builder setHpCodeRate(@CodeRate int hpCodeRate) {
+            mHpCodeRate = hpCodeRate;
             return this;
         }
         /**
          * Sets Code Rate for Low Priority level.
          */
         @NonNull
-        public Builder setLpCoderate(@Coderate int lpCoderate) {
-            mLpCoderate = lpCoderate;
+        public Builder setLpCodeRate(@CodeRate int lpCodeRate) {
+            mLpCodeRate = lpCodeRate;
             return this;
         }
         /**
@@ -633,7 +635,7 @@
         @NonNull
         public DvbtFrontendSettings build() {
             return new DvbtFrontendSettings(mFrequency, mTransmissionMode, mBandwidth,
-                    mConstellation, mHierarchy, mHpCoderate, mLpCoderate, mGuardInterval,
+                    mConstellation, mHierarchy, mHpCodeRate, mLpCodeRate, mGuardInterval,
                     mIsHighPriority, mStandard, mIsMiso, mPlpMode, mPlpId, mPlpGroupId);
         }
 
diff --git a/media/java/android/media/tv/tuner/frontend/FrontendCapabilities.java b/media/java/android/media/tv/tuner/frontend/FrontendCapabilities.java
index e4f66b8..c03133d 100644
--- a/media/java/android/media/tv/tuner/frontend/FrontendCapabilities.java
+++ b/media/java/android/media/tv/tuner/frontend/FrontendCapabilities.java
@@ -16,10 +16,13 @@
 
 package android.media.tv.tuner.frontend;
 
+import android.annotation.SystemApi;
+
 /**
  * Frontend capabilities.
  *
  * @hide
  */
+@SystemApi
 public abstract class FrontendCapabilities {
 }
diff --git a/media/java/android/media/tv/tuner/frontend/FrontendInfo.java b/media/java/android/media/tv/tuner/frontend/FrontendInfo.java
index 360c84a..696d839 100644
--- a/media/java/android/media/tv/tuner/frontend/FrontendInfo.java
+++ b/media/java/android/media/tv/tuner/frontend/FrontendInfo.java
@@ -17,6 +17,7 @@
 package android.media.tv.tuner.frontend;
 
 import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.media.tv.tuner.frontend.FrontendSettings.Type;
 import android.media.tv.tuner.frontend.FrontendStatus.FrontendStatusType;
 import android.util.Range;
@@ -26,6 +27,7 @@
  *
  * @hide
  */
+@SystemApi
 public class FrontendInfo {
     private final int mId;
     private final int mType;
@@ -102,12 +104,14 @@
      * @return An array of supported status types.
      */
     @FrontendStatusType
+    @NonNull
     public int[] getStatusCapabilities() {
         return mStatusCaps;
     }
     /**
      * Gets frontend capabilities.
      */
+    @NonNull
     public FrontendCapabilities getFrontendCapability() {
         return mFrontendCap;
     }
diff --git a/media/java/android/media/tv/tuner/frontend/FrontendSettings.java b/media/java/android/media/tv/tuner/frontend/FrontendSettings.java
index b80b7cd..9071526 100644
--- a/media/java/android/media/tv/tuner/frontend/FrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/FrontendSettings.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.IntRange;
+import android.annotation.LongDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.hardware.tv.tuner.V1_0.Constants;
@@ -33,8 +34,9 @@
 @SystemApi
 public abstract class FrontendSettings {
     /** @hide */
-    @IntDef({TYPE_UNDEFINED, TYPE_ANALOG, TYPE_ATSC, TYPE_ATSC3, TYPE_DVBC, TYPE_DVBS, TYPE_DVBT,
-            TYPE_ISDBS, TYPE_ISDBS3, TYPE_ISDBT})
+    @IntDef(prefix = "TYPE_",
+            value = {TYPE_UNDEFINED, TYPE_ANALOG, TYPE_ATSC, TYPE_ATSC3, TYPE_DVBC, TYPE_DVBS,
+                    TYPE_DVBT, TYPE_ISDBS, TYPE_ISDBS3, TYPE_ISDBT})
     @Retention(RetentionPolicy.SOURCE)
     public @interface Type {}
 
@@ -79,10 +81,173 @@
      */
     public static final int TYPE_ISDBT = Constants.FrontendType.ISDBT;
 
-    private final int mFrequency;
+
 
     /** @hide */
-    public FrontendSettings(int frequency) {
+    @LongDef(flag = true,
+            prefix = "FEC_",
+            value = {FEC_UNDEFINED, FEC_AUTO, FEC_1_2, FEC_1_3, FEC_1_4, FEC_1_5, FEC_2_3, FEC_2_5,
+            FEC_2_9, FEC_3_4, FEC_3_5, FEC_4_5, FEC_4_15, FEC_5_6, FEC_5_9, FEC_6_7, FEC_7_8,
+            FEC_7_9, FEC_7_15, FEC_8_9, FEC_8_15, FEC_9_10, FEC_9_20, FEC_11_15, FEC_11_20,
+            FEC_11_45, FEC_13_18, FEC_13_45, FEC_14_45, FEC_23_36, FEC_25_36, FEC_26_45, FEC_28_45,
+            FEC_29_45, FEC_31_45, FEC_32_45, FEC_77_90})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface InnerFec {}
+
+    /**
+     * FEC not defined.
+     */
+    public static final long FEC_UNDEFINED = Constants.FrontendInnerFec.FEC_UNDEFINED;
+    /**
+     * hardware is able to detect and set FEC automatically.
+     */
+    public static final long FEC_AUTO = Constants.FrontendInnerFec.AUTO;
+    /**
+     * 1/2 conv. code rate.
+     */
+    public static final long FEC_1_2 = Constants.FrontendInnerFec.FEC_1_2;
+    /**
+     * 1/3 conv. code rate.
+     */
+    public static final long FEC_1_3 = Constants.FrontendInnerFec.FEC_1_3;
+    /**
+     * 1/4 conv. code rate.
+     */
+    public static final long FEC_1_4 = Constants.FrontendInnerFec.FEC_1_4;
+    /**
+     * 1/5 conv. code rate.
+     */
+    public static final long FEC_1_5 = Constants.FrontendInnerFec.FEC_1_5;
+    /**
+     * 2/3 conv. code rate.
+     */
+    public static final long FEC_2_3 = Constants.FrontendInnerFec.FEC_2_3;
+    /**
+     * 2/5 conv. code rate.
+     */
+    public static final long FEC_2_5 = Constants.FrontendInnerFec.FEC_2_5;
+    /**
+     * 2/9 conv. code rate.
+     */
+    public static final long FEC_2_9 = Constants.FrontendInnerFec.FEC_2_9;
+    /**
+     * 3/4 conv. code rate.
+     */
+    public static final long FEC_3_4 = Constants.FrontendInnerFec.FEC_3_4;
+    /**
+     * 3/5 conv. code rate.
+     */
+    public static final long FEC_3_5 = Constants.FrontendInnerFec.FEC_3_5;
+    /**
+     * 4/5 conv. code rate.
+     */
+    public static final long FEC_4_5 = Constants.FrontendInnerFec.FEC_4_5;
+    /**
+     * 4/15 conv. code rate.
+     */
+    public static final long FEC_4_15 = Constants.FrontendInnerFec.FEC_4_15;
+    /**
+     * 5/6 conv. code rate.
+     */
+    public static final long FEC_5_6 = Constants.FrontendInnerFec.FEC_5_6;
+    /**
+     * 5/9 conv. code rate.
+     */
+    public static final long FEC_5_9 = Constants.FrontendInnerFec.FEC_5_9;
+    /**
+     * 6/7 conv. code rate.
+     */
+    public static final long FEC_6_7 = Constants.FrontendInnerFec.FEC_6_7;
+    /**
+     * 7/8 conv. code rate.
+     */
+    public static final long FEC_7_8 = Constants.FrontendInnerFec.FEC_7_8;
+    /**
+     * 7/9 conv. code rate.
+     */
+    public static final long FEC_7_9 = Constants.FrontendInnerFec.FEC_7_9;
+    /**
+     * 7/15 conv. code rate.
+     */
+    public static final long FEC_7_15 = Constants.FrontendInnerFec.FEC_7_15;
+    /**
+     * 8/9 conv. code rate.
+     */
+    public static final long FEC_8_9 = Constants.FrontendInnerFec.FEC_8_9;
+    /**
+     * 8/15 conv. code rate.
+     */
+    public static final long FEC_8_15 = Constants.FrontendInnerFec.FEC_8_15;
+    /**
+     * 9/10 conv. code rate.
+     */
+    public static final long FEC_9_10 = Constants.FrontendInnerFec.FEC_9_10;
+    /**
+     * 9/20 conv. code rate.
+     */
+    public static final long FEC_9_20 = Constants.FrontendInnerFec.FEC_9_20;
+    /**
+     * 11/15 conv. code rate.
+     */
+    public static final long FEC_11_15 = Constants.FrontendInnerFec.FEC_11_15;
+    /**
+     * 11/20 conv. code rate.
+     */
+    public static final long FEC_11_20 = Constants.FrontendInnerFec.FEC_11_20;
+    /**
+     * 11/45 conv. code rate.
+     */
+    public static final long FEC_11_45 = Constants.FrontendInnerFec.FEC_11_45;
+    /**
+     * 13/18 conv. code rate.
+     */
+    public static final long FEC_13_18 = Constants.FrontendInnerFec.FEC_13_18;
+    /**
+     * 13/45 conv. code rate.
+     */
+    public static final long FEC_13_45 = Constants.FrontendInnerFec.FEC_13_45;
+    /**
+     * 14/45 conv. code rate.
+     */
+    public static final long FEC_14_45 = Constants.FrontendInnerFec.FEC_14_45;
+    /**
+     * 23/36 conv. code rate.
+     */
+    public static final long FEC_23_36 = Constants.FrontendInnerFec.FEC_23_36;
+    /**
+     * 25/36 conv. code rate.
+     */
+    public static final long FEC_25_36 = Constants.FrontendInnerFec.FEC_25_36;
+    /**
+     * 26/45 conv. code rate.
+     */
+    public static final long FEC_26_45 = Constants.FrontendInnerFec.FEC_26_45;
+    /**
+     * 28/45 conv. code rate.
+     */
+    public static final long FEC_28_45 = Constants.FrontendInnerFec.FEC_28_45;
+    /**
+     * 29/45 conv. code rate.
+     */
+    public static final long FEC_29_45 = Constants.FrontendInnerFec.FEC_29_45;
+    /**
+     * 31/45 conv. code rate.
+     */
+    public static final long FEC_31_45 = Constants.FrontendInnerFec.FEC_31_45;
+    /**
+     * 32/45 conv. code rate.
+     */
+    public static final long FEC_32_45 = Constants.FrontendInnerFec.FEC_32_45;
+    /**
+     * 77/90 conv. code rate.
+     */
+    public static final long FEC_77_90 = Constants.FrontendInnerFec.FEC_77_90;
+
+
+
+    private final int mFrequency;
+
+    FrontendSettings(int frequency) {
         mFrequency = frequency;
     }
 
diff --git a/media/java/android/media/tv/tuner/frontend/FrontendStatus.java b/media/java/android/media/tv/tuner/frontend/FrontendStatus.java
index 088adff..c1b17d3 100644
--- a/media/java/android/media/tv/tuner/frontend/FrontendStatus.java
+++ b/media/java/android/media/tv/tuner/frontend/FrontendStatus.java
@@ -18,19 +18,19 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.hardware.tv.tuner.V1_0.Constants;
 import android.media.tv.tuner.Lnb;
-import android.media.tv.tuner.TunerConstants.FrontendInnerFec;
-import android.media.tv.tuner.TunerConstants.FrontendModulation;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
 /**
- * Frontend status
+ * Frontend status.
  *
  * @hide
  */
+@SystemApi
 public class FrontendStatus {
 
     /** @hide */
@@ -160,6 +160,52 @@
             Constants.FrontendStatusType.ATSC3_PLP_INFO;
 
 
+    /** @hide */
+    @IntDef(value = {
+            DvbcFrontendSettings.MODULATION_UNDEFINED,
+            DvbcFrontendSettings.MODULATION_AUTO,
+            DvbcFrontendSettings.MODULATION_MOD_16QAM,
+            DvbcFrontendSettings.MODULATION_MOD_32QAM,
+            DvbcFrontendSettings.MODULATION_MOD_64QAM,
+            DvbcFrontendSettings.MODULATION_MOD_128QAM,
+            DvbcFrontendSettings.MODULATION_MOD_256QAM,
+            DvbsFrontendSettings.MODULATION_UNDEFINED,
+            DvbsFrontendSettings.MODULATION_AUTO,
+            DvbsFrontendSettings.MODULATION_MOD_QPSK,
+            DvbsFrontendSettings.MODULATION_MOD_8PSK,
+            DvbsFrontendSettings.MODULATION_MOD_16QAM,
+            DvbsFrontendSettings.MODULATION_MOD_16PSK,
+            DvbsFrontendSettings.MODULATION_MOD_32PSK,
+            DvbsFrontendSettings.MODULATION_MOD_ACM,
+            DvbsFrontendSettings.MODULATION_MOD_8APSK,
+            DvbsFrontendSettings.MODULATION_MOD_16APSK,
+            DvbsFrontendSettings.MODULATION_MOD_32APSK,
+            DvbsFrontendSettings.MODULATION_MOD_64APSK,
+            DvbsFrontendSettings.MODULATION_MOD_128APSK,
+            DvbsFrontendSettings.MODULATION_MOD_256APSK,
+            DvbsFrontendSettings.MODULATION_MOD_RESERVED,
+            IsdbsFrontendSettings.MODULATION_UNDEFINED,
+            IsdbsFrontendSettings.MODULATION_AUTO,
+            IsdbsFrontendSettings.MODULATION_MOD_BPSK,
+            IsdbsFrontendSettings.MODULATION_MOD_QPSK,
+            IsdbsFrontendSettings.MODULATION_MOD_TC8PSK,
+            Isdbs3FrontendSettings.MODULATION_UNDEFINED,
+            Isdbs3FrontendSettings.MODULATION_AUTO,
+            Isdbs3FrontendSettings.MODULATION_MOD_BPSK,
+            Isdbs3FrontendSettings.MODULATION_MOD_QPSK,
+            Isdbs3FrontendSettings.MODULATION_MOD_8PSK,
+            Isdbs3FrontendSettings.MODULATION_MOD_16APSK,
+            Isdbs3FrontendSettings.MODULATION_MOD_32APSK,
+            IsdbtFrontendSettings.MODULATION_UNDEFINED,
+            IsdbtFrontendSettings.MODULATION_AUTO,
+            IsdbtFrontendSettings.MODULATION_MOD_DQPSK,
+            IsdbtFrontendSettings.MODULATION_MOD_QPSK,
+            IsdbtFrontendSettings.MODULATION_MOD_16QAM,
+            IsdbtFrontendSettings.MODULATION_MOD_64QAM})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface FrontendModulation {}
+
+
     private Boolean mIsDemodLocked;
     private Integer mSnr;
     private Integer mBer;
@@ -273,7 +319,7 @@
      *  Gets Inner Forward Error Correction type as specified in ETSI EN 300 468 V1.15.1
      *  and ETSI EN 302 307-2 V1.1.1.
      */
-    @FrontendInnerFec
+    @FrontendSettings.InnerFec
     public long getFec() {
         if (mInnerFec == null) {
             throw new IllegalStateException();
diff --git a/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendCapabilities.java b/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendCapabilities.java
index 61cba1c..573f379 100644
--- a/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendCapabilities.java
+++ b/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendCapabilities.java
@@ -16,17 +16,21 @@
 
 package android.media.tv.tuner.frontend;
 
+import android.annotation.SystemApi;
+
 /**
  * ISDBS-3 Capabilities.
+ *
  * @hide
  */
+@SystemApi
 public class Isdbs3FrontendCapabilities extends FrontendCapabilities {
     private final int mModulationCap;
-    private final int mCoderateCap;
+    private final int mCodeRateCap;
 
-    private Isdbs3FrontendCapabilities(int modulationCap, int coderateCap) {
+    private Isdbs3FrontendCapabilities(int modulationCap, int codeRateCap) {
         mModulationCap = modulationCap;
-        mCoderateCap = coderateCap;
+        mCodeRateCap = codeRateCap;
     }
 
     /**
@@ -39,8 +43,8 @@
     /**
      * Gets code rate capability.
      */
-    @Isdbs3FrontendSettings.Coderate
+    @Isdbs3FrontendSettings.CodeRate
     public int getCodeRateCapability() {
-        return mCoderateCap;
+        return mCodeRateCap;
     }
 }
diff --git a/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java b/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java
index a83d771..9b0e533 100644
--- a/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.content.Context;
 import android.hardware.tv.tuner.V1_0.Constants;
 import android.media.tv.tuner.TunerUtils;
@@ -28,8 +29,10 @@
 
 /**
  * Frontend settings for ISDBS-3.
+ *
  * @hide
  */
+@SystemApi
 public class Isdbs3FrontendSettings extends FrontendSettings {
     /** @hide */
     @IntDef(flag = true,
@@ -76,7 +79,7 @@
             value = {CODERATE_UNDEFINED, CODERATE_AUTO, CODERATE_1_3, CODERATE_2_5, CODERATE_1_2,
                     CODERATE_3_5, CODERATE_2_3, CODERATE_3_4, CODERATE_7_9, CODERATE_4_5,
                     CODERATE_5_6, CODERATE_7_8, CODERATE_9_10})
-    public @interface Coderate {}
+    public @interface CodeRate {}
 
     /**
      * Code rate undefined.
@@ -150,17 +153,17 @@
     private final int mStreamId;
     private final int mStreamIdType;
     private final int mModulation;
-    private final int mCoderate;
+    private final int mCodeRate;
     private final int mSymbolRate;
     private final int mRolloff;
 
     private Isdbs3FrontendSettings(int frequency, int streamId, int streamIdType, int modulation,
-            int coderate, int symbolRate, int rolloff) {
+            int codeRate, int symbolRate, int rolloff) {
         super(frequency);
         mStreamId = streamId;
         mStreamIdType = streamIdType;
         mModulation = modulation;
-        mCoderate = coderate;
+        mCodeRate = codeRate;
         mSymbolRate = symbolRate;
         mRolloff = rolloff;
     }
@@ -188,9 +191,9 @@
     /**
      * Gets Code rate.
      */
-    @Coderate
-    public int getCoderate() {
-        return mCoderate;
+    @CodeRate
+    public int getCodeRate() {
+        return mCodeRate;
     }
     /**
      * Gets Symbol Rate in symbols per second.
@@ -225,7 +228,7 @@
         private int mStreamId;
         private int mStreamIdType;
         private int mModulation;
-        private int mCoderate;
+        private int mCodeRate;
         private int mSymbolRate;
         private int mRolloff;
 
@@ -260,8 +263,8 @@
          * Sets Code rate.
          */
         @NonNull
-        public Builder setCoderate(@Coderate int coderate) {
-            mCoderate = coderate;
+        public Builder setCodeRate(@CodeRate int codeRate) {
+            mCodeRate = codeRate;
             return this;
         }
         /**
@@ -287,7 +290,7 @@
         @NonNull
         public Isdbs3FrontendSettings build() {
             return new Isdbs3FrontendSettings(mFrequency, mStreamId, mStreamIdType, mModulation,
-                    mCoderate, mSymbolRate, mRolloff);
+                    mCodeRate, mSymbolRate, mRolloff);
         }
 
         @Override
diff --git a/media/java/android/media/tv/tuner/frontend/IsdbsFrontendCapabilities.java b/media/java/android/media/tv/tuner/frontend/IsdbsFrontendCapabilities.java
index 8e5ecc4..38d2f1d 100644
--- a/media/java/android/media/tv/tuner/frontend/IsdbsFrontendCapabilities.java
+++ b/media/java/android/media/tv/tuner/frontend/IsdbsFrontendCapabilities.java
@@ -16,17 +16,21 @@
 
 package android.media.tv.tuner.frontend;
 
+import android.annotation.SystemApi;
+
 /**
  * ISDBS Capabilities.
+ *
  * @hide
  */
+@SystemApi
 public class IsdbsFrontendCapabilities extends FrontendCapabilities {
     private final int mModulationCap;
-    private final int mCoderateCap;
+    private final int mCodeRateCap;
 
-    private IsdbsFrontendCapabilities(int modulationCap, int coderateCap) {
+    private IsdbsFrontendCapabilities(int modulationCap, int codeRateCap) {
         mModulationCap = modulationCap;
-        mCoderateCap = coderateCap;
+        mCodeRateCap = codeRateCap;
     }
 
     /**
@@ -39,8 +43,8 @@
     /**
      * Gets code rate capability.
      */
-    @IsdbsFrontendSettings.Coderate
+    @IsdbsFrontendSettings.CodeRate
     public int getCodeRateCapability() {
-        return mCoderateCap;
+        return mCodeRateCap;
     }
 }
diff --git a/media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java
index bb809bf..14c08b1 100644
--- a/media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.content.Context;
 import android.hardware.tv.tuner.V1_0.Constants;
 import android.media.tv.tuner.TunerUtils;
@@ -28,8 +29,10 @@
 
 /**
  * Frontend settings for ISDBS.
+ *
  * @hide
  */
+@SystemApi
 public class IsdbsFrontendSettings extends FrontendSettings {
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
@@ -81,11 +84,10 @@
     /** @hide */
     @IntDef(flag = true,
             prefix = "CODERATE_",
-            value = {CODERATE_UNDEFINED, CODERATE_AUTO,
-            CODERATE_1_2, CODERATE_2_3, CODERATE_3_4,
-            CODERATE_5_6, CODERATE_7_8})
+            value = {CODERATE_UNDEFINED, CODERATE_AUTO, CODERATE_1_2, CODERATE_2_3, CODERATE_3_4,
+                    CODERATE_5_6, CODERATE_7_8})
     @Retention(RetentionPolicy.SOURCE)
-    public @interface Coderate {}
+    public @interface CodeRate {}
 
     /**
      * Code rate undefined.
@@ -125,7 +127,7 @@
     /**
      * Rolloff type undefined.
      */
-    public static final int ROLLOFF_UNDEFINED = Constants.FrontendIsdbs3Rolloff.UNDEFINED;
+    public static final int ROLLOFF_UNDEFINED = Constants.FrontendIsdbsRolloff.UNDEFINED;
     /**
      * 0,35 rolloff.
      */
@@ -135,17 +137,17 @@
     private final int mStreamId;
     private final int mStreamIdType;
     private final int mModulation;
-    private final int mCoderate;
+    private final int mCodeRate;
     private final int mSymbolRate;
     private final int mRolloff;
 
     private IsdbsFrontendSettings(int frequency, int streamId, int streamIdType, int modulation,
-            int coderate, int symbolRate, int rolloff) {
+            int codeRate, int symbolRate, int rolloff) {
         super(frequency);
         mStreamId = streamId;
         mStreamIdType = streamIdType;
         mModulation = modulation;
-        mCoderate = coderate;
+        mCodeRate = codeRate;
         mSymbolRate = symbolRate;
         mRolloff = rolloff;
     }
@@ -173,9 +175,9 @@
     /**
      * Gets Code rate.
      */
-    @Coderate
-    public int getCoderate() {
-        return mCoderate;
+    @CodeRate
+    public int getCodeRate() {
+        return mCodeRate;
     }
     /**
      * Gets Symbol Rate in symbols per second.
@@ -210,7 +212,7 @@
         private int mStreamId;
         private int mStreamIdType;
         private int mModulation;
-        private int mCoderate;
+        private int mCodeRate;
         private int mSymbolRate;
         private int mRolloff;
 
@@ -245,8 +247,8 @@
          * Sets Code rate.
          */
         @NonNull
-        public Builder setCoderate(@Coderate int coderate) {
-            mCoderate = coderate;
+        public Builder setCodeRate(@CodeRate int codeRate) {
+            mCodeRate = codeRate;
             return this;
         }
         /**
@@ -272,7 +274,7 @@
         @NonNull
         public IsdbsFrontendSettings build() {
             return new IsdbsFrontendSettings(mFrequency, mStreamId, mStreamIdType, mModulation,
-                    mCoderate, mSymbolRate, mRolloff);
+                    mCodeRate, mSymbolRate, mRolloff);
         }
 
         @Override
diff --git a/media/java/android/media/tv/tuner/frontend/IsdbtFrontendCapabilities.java b/media/java/android/media/tv/tuner/frontend/IsdbtFrontendCapabilities.java
index 19f04de..ffebc5a 100644
--- a/media/java/android/media/tv/tuner/frontend/IsdbtFrontendCapabilities.java
+++ b/media/java/android/media/tv/tuner/frontend/IsdbtFrontendCapabilities.java
@@ -16,23 +16,27 @@
 
 package android.media.tv.tuner.frontend;
 
+import android.annotation.SystemApi;
+
 /**
  * ISDBT Capabilities.
+ *
  * @hide
  */
+@SystemApi
 public class IsdbtFrontendCapabilities extends FrontendCapabilities {
     private final int mModeCap;
     private final int mBandwidthCap;
     private final int mModulationCap;
-    private final int mCoderateCap;
+    private final int mCodeRateCap;
     private final int mGuardIntervalCap;
 
     private IsdbtFrontendCapabilities(int modeCap, int bandwidthCap, int modulationCap,
-            int coderateCap, int guardIntervalCap) {
+            int codeRateCap, int guardIntervalCap) {
         mModeCap = modeCap;
         mBandwidthCap = bandwidthCap;
         mModulationCap = modulationCap;
-        mCoderateCap = coderateCap;
+        mCodeRateCap = codeRateCap;
         mGuardIntervalCap = guardIntervalCap;
     }
 
@@ -60,9 +64,9 @@
     /**
      * Gets code rate capability.
      */
-    @DvbtFrontendSettings.Coderate
+    @DvbtFrontendSettings.CodeRate
     public int getCodeRateCapability() {
-        return mCoderateCap;
+        return mCodeRateCap;
     }
     /**
      * Gets guard interval capability.
diff --git a/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java
index 1510193..de3c80d 100644
--- a/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java
@@ -19,17 +19,21 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.content.Context;
 import android.hardware.tv.tuner.V1_0.Constants;
 import android.media.tv.tuner.TunerUtils;
+import android.media.tv.tuner.frontend.DvbtFrontendSettings.CodeRate;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
 /**
  * Frontend settings for ISDBT.
+ *
  * @hide
  */
+@SystemApi
 public class IsdbtFrontendSettings extends FrontendSettings {
     /** @hide */
     @IntDef(flag = true,
@@ -125,16 +129,18 @@
 
     private final int mModulation;
     private final int mBandwidth;
-    private final int mCoderate;
+    private final int mMode;
+    private final int mCodeRate;
     private final int mGuardInterval;
     private final int mServiceAreaId;
 
-    private IsdbtFrontendSettings(int frequency, int modulation, int bandwidth, int coderate,
-            int guardInterval, int serviceAreaId) {
+    private IsdbtFrontendSettings(int frequency, int modulation, int bandwidth, int mode,
+            int codeRate, int guardInterval, int serviceAreaId) {
         super(frequency);
         mModulation = modulation;
         mBandwidth = bandwidth;
-        mCoderate = coderate;
+        mMode = mode;
+        mCodeRate = codeRate;
         mGuardInterval = guardInterval;
         mServiceAreaId = serviceAreaId;
     }
@@ -154,11 +160,18 @@
         return mBandwidth;
     }
     /**
+     * Gets ISDBT mode.
+     */
+    @Mode
+    public int getMode() {
+        return mMode;
+    }
+    /**
      * Gets Code rate.
      */
-    @DvbtFrontendSettings.Coderate
-    public int getCoderate() {
-        return mCoderate;
+    @CodeRate
+    public int getCodeRate() {
+        return mCodeRate;
     }
     /**
      * Gets Guard Interval.
@@ -192,7 +205,8 @@
     public static class Builder extends FrontendSettings.Builder<Builder> {
         private int mModulation;
         private int mBandwidth;
-        private int mCoderate;
+        private int mMode;
+        private int mCodeRate;
         private int mGuardInterval;
         private int mServiceAreaId;
 
@@ -216,11 +230,19 @@
             return this;
         }
         /**
+         * Sets ISDBT mode.
+         */
+        @NonNull
+        public Builder setMode(@Mode int mode) {
+            mMode = mode;
+            return this;
+        }
+        /**
          * Sets Code rate.
          */
         @NonNull
-        public Builder setCoderate(@DvbtFrontendSettings.Coderate int coderate) {
-            mCoderate = coderate;
+        public Builder setCodeRate(@CodeRate int codeRate) {
+            mCodeRate = codeRate;
             return this;
         }
         /**
@@ -245,8 +267,8 @@
          */
         @NonNull
         public IsdbtFrontendSettings build() {
-            return new IsdbtFrontendSettings(
-                    mFrequency, mModulation, mBandwidth, mCoderate, mGuardInterval, mServiceAreaId);
+            return new IsdbtFrontendSettings(mFrequency, mModulation, mBandwidth, mMode, mCodeRate,
+                    mGuardInterval, mServiceAreaId);
         }
 
         @Override
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaFileTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaFileTest.java
index 481f479..507dd4a 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaFileTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaFileTest.java
@@ -19,6 +19,7 @@
 import static android.media.MediaFile.getFormatCode;
 import static android.media.MediaFile.getMimeType;
 import static android.media.MediaFile.isAudioMimeType;
+import static android.media.MediaFile.isDocumentMimeType;
 import static android.media.MediaFile.isImageMimeType;
 import static android.media.MediaFile.isPlayListMimeType;
 import static android.media.MediaFile.isVideoMimeType;
@@ -88,7 +89,15 @@
         assertTrue(isPlayListMimeType(mimeMap.guessMimeTypeFromExtension("wpl")));
         assertTrue(isPlayListMimeType(mimeMap.guessMimeTypeFromExtension("m3u")));
         assertTrue(isPlayListMimeType(mimeMap.guessMimeTypeFromExtension("m3u8")));
-        assertTrue(isPlayListMimeType(mimeMap.guessMimeTypeFromExtension("asf")));
+    }
+
+    @Test
+    public void testDocument() throws Exception {
+        assertTrue(isDocumentMimeType("text/csv"));
+        assertTrue(isDocumentMimeType("text/plain"));
+        assertTrue(isDocumentMimeType("application/pdf"));
+        assertTrue(isDocumentMimeType("application/msword"));
+        assertFalse(isDocumentMimeType("audio/mpeg"));
     }
 
     @Test
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java
index daaa868..e0b4545 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java
@@ -36,6 +36,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 import static org.testng.Assert.assertThrows;
 
@@ -693,6 +694,14 @@
         assertFalse(systemController.isReleased());
     }
 
+    @Test
+    public void testControllers() {
+        List<RoutingController> controllers = mRouter2.getControllers();
+        assertNotNull(controllers);
+        assertFalse(controllers.isEmpty());
+        assertSame(mRouter2.getSystemController(), controllers.get(0));
+    }
+
     // Helper for getting routes easily
     static Map<String, MediaRoute2Info> createRouteMap(List<MediaRoute2Info> routes) {
         Map<String, MediaRoute2Info> routeMap = new HashMap<>();
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
index 7726e90..4a2044a 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
@@ -246,7 +246,7 @@
             }
         });
 
-        assertEquals(0, mManager.getRoutingControllers(mPackageName).size());
+        assertEquals(1, mManager.getRoutingControllers(mPackageName).size());
 
         mManager.selectRoute(mPackageName, routes.get(ROUTE_ID1));
         latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
@@ -254,14 +254,14 @@
         List<MediaRouter2Manager.RoutingController> controllers =
                 mManager.getRoutingControllers(mPackageName);
 
-        assertEquals(1, controllers.size());
+        assertEquals(2, controllers.size());
 
-        MediaRouter2Manager.RoutingController routingController = controllers.get(0);
+        MediaRouter2Manager.RoutingController routingController = controllers.get(1);
         awaitOnRouteChangedManager(
                 () -> routingController.release(),
                 ROUTE_ID1,
                 route -> TextUtils.equals(route.getClientPackageName(), null));
-        assertEquals(0, mManager.getRoutingControllers(mPackageName).size());
+        assertEquals(1, mManager.getRoutingControllers(mPackageName).size());
     }
 
     /**
@@ -290,8 +290,8 @@
         List<MediaRouter2Manager.RoutingController> controllers =
                 mManager.getRoutingControllers(mPackageName);
 
-        assertEquals(1, controllers.size());
-        MediaRouter2Manager.RoutingController routingController = controllers.get(0);
+        assertEquals(2, controllers.size());
+        MediaRouter2Manager.RoutingController routingController = controllers.get(1);
 
         awaitOnRouteChangedManager(
                 () -> mManager.selectRoute(mPackageName, routes.get(ROUTE_ID5_TO_TRANSFER_TO)),
diff --git a/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java b/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
index 50f858e..e87148e 100644
--- a/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
+++ b/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
@@ -211,6 +211,12 @@
 
     private int performBackupInternal(
             PackageInfo packageInfo, ParcelFileDescriptor data, int flags) {
+        if ((flags & BackupTransport.FLAG_DATA_NOT_CHANGED) != 0) {
+            // For unchanged data notifications we do nothing and tell the
+            // caller everything was OK
+            return BackupTransport.TRANSPORT_OK;
+        }
+
         boolean isIncremental = (flags & FLAG_INCREMENTAL) != 0;
         boolean isNonIncremental = (flags & FLAG_NON_INCREMENTAL) != 0;
 
diff --git a/packages/SettingsLib/SearchWidget/res/values-pt-rPT/strings.xml b/packages/SettingsLib/SearchWidget/res/values-pt-rPT/strings.xml
index ddf838e..85a8d73 100644
--- a/packages/SettingsLib/SearchWidget/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-pt-rPT/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="search_menu" msgid="1914043873178389845">"Pesquisar definições"</string>
+    <string name="search_menu" msgid="1914043873178389845">"Pesquisa de definições"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-af/arrays.xml b/packages/SettingsLib/res/values-af/arrays.xml
index d9aaf7d..8a02c77 100644
--- a/packages/SettingsLib/res/values-af/arrays.xml
+++ b/packages/SettingsLib/res/values-af/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (verstek)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Gebruik stelselkeuse (verstek)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 2590338..2b143e4 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Aktiveer Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP-weergawe"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Kies Bluetooth AVRCP-weergawe"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetooth MAP-weergawe"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Kies Bluetooth MAP-weergawe"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth-oudiokodek"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Gebruik Bluetooth-oudiokodek\nKeuse"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth-oudiovoorbeeldkoers"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Kontroleer programme wat via ADB/ADT geïnstalleer is vir skadelike gedrag."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth-toestelle sonder name (net MAC-adresse) sal gewys word"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Deaktiveer die Bluetooth-kenmerk vir absolute volume indien daar volumeprobleme met afgeleë toestelle is, soos onaanvaarbare harde klank of geen beheer nie."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Aktiveer die Bluetooth Gabeldorsche-kenmerkstapel."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Aktiveer die Bluetooth Gabeldorsche-kenmerkstapel."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Plaaslike terminaal"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Aktiveer terminaalprogram wat plaaslike skermtoegang bied"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP-kontrolering"</string>
diff --git a/packages/SettingsLib/res/values-am/arrays.xml b/packages/SettingsLib/res/values-am/arrays.xml
index fff7cae3..6a9334e 100644
--- a/packages/SettingsLib/res/values-am/arrays.xml
+++ b/packages/SettingsLib/res/values-am/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (ነባሪ)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"የስርዓቱን ምርጫ (ነባሪ) ተጠቀም"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 8277711..2a93e017 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorscheን አንቃ"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"የብሉቱዝ AVRCP ስሪት"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"የብሉቱዝ AVRCP ስሪት ይምረጡ"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"የብሉቱዝ MAP ስሪት"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"የብሉቱዝ MAP ስሪቱን ይምረጡ"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"የብሉቱዝ ኦዲዮ ኮዴክ"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"የብሉቱዝ ኦዲዮ ኮዴክ አስጀምር\nምርጫ"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"የብሉቱዝ ኦዲዮ ናሙና ፍጥነት"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"በADB/ADT በኩል የተጫኑ መተግበሪያዎች ጎጂ ባህሪ ካላቸው ያረጋግጡ።"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"የብሉቱዝ መሣሪያዎች ያለ ስሞች (MAC አድራሻዎች ብቻ) ይታያሉ"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"እንደ ተቀባይነት በሌለው ደረጃ ድምፁ ከፍ ማለት ወይም መቆጣጠር አለመቻል ያሉ ከሩቅ መሣሪያዎች ጋር የድምፅ ችግር በሚኖርበት ጊዜ የብሉቱዝ ፍጹማዊ ድምፅን ባሕሪ ያሰናክላል።"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"የብሉቱዝ Gabeldorche ባህሪ ቁልልን ያነቃል።"</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"የብሉቱዝ Gabeldorsche ባህሪ ቁልሉን ያነቃል።"</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"አካባቢያዊ ተርሚናል"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"የአካባቢያዊ ሼል መዳረሻ የሚያቀርብ የተርሚናል መተግበሪያ አንቃ"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"የHDCP ምልከታ"</string>
diff --git a/packages/SettingsLib/res/values-ar/arrays.xml b/packages/SettingsLib/res/values-ar/arrays.xml
index b4f5253..851a3d8 100644
--- a/packages/SettingsLib/res/values-ar/arrays.xml
+++ b/packages/SettingsLib/res/values-ar/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"‏MAP 1.2 (الإعداد الافتراضي)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"استخدام اختيار النظام (تلقائي)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 43d2ece..5485656 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"‏تفعيل Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"‏إصدار Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"‏اختيار إصدار Bluetooth AVRCP"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"‏إصدار Bluetooth MAP"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"‏اختيار إصدار Bluetooth MAP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"برنامج ترميز صوت بلوتوث"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"اختيار برنامج ترميز الصوت لمشغّل\nالبلوتوث"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"معدّل عيّنة صوت بلوتوث"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"‏التحقق من التطبيقات المثبتة عبر ADB/ADT لكشف السلوك الضار"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"‏سيتم عرض أجهزة البلوتوث بدون أسماء (عناوين MAC فقط)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"لإيقاف ميزة مستوى الصوت المطلق للبلوتوث في حال حدوث مشاكل متعلقة بمستوى الصوت في الأجهزة البعيدة، مثل مستوى صوت عالٍ بشكل غير مقبول أو عدم إمكانية التحكّم في الصوت"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"‏تفعيل حِزم ميزة Bluetooth Gabeldorche"</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"‏تفعيل حِزم ميزة Bluetooth Gabeldorsche"</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"تطبيق طرفي محلي"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"تفعيل تطبيق طرفي يوفر إمكانية الدخول إلى واجهة النظام المحلية"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"‏التحقق من HDCP"</string>
@@ -435,7 +437,7 @@
     <string name="screen_zoom_summary_extremely_large" msgid="1438045624562358554">"أكبر مستوى"</string>
     <string name="screen_zoom_summary_custom" msgid="3468154096832912210">"مخصص (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="content_description_menu_button" msgid="6254844309171779931">"القائمة"</string>
-    <string name="retail_demo_reset_message" msgid="5392824901108195463">"إدخال كلمة المرور لإعادة الضبط بحسب بيانات المصنع في الوضع التجريبي"</string>
+    <string name="retail_demo_reset_message" msgid="5392824901108195463">"إدخال كلمة المرور لإعادة الضبط على الإعدادات الأصلية في الوضع التجريبي"</string>
     <string name="retail_demo_reset_next" msgid="3688129033843885362">"التالي"</string>
     <string name="retail_demo_reset_title" msgid="1866911701095959800">"يلزم توفر كلمة مرور"</string>
     <string name="active_input_method_subtypes" msgid="4232680535471633046">"طرق الإدخال النشطة"</string>
diff --git a/packages/SettingsLib/res/values-as/arrays.xml b/packages/SettingsLib/res/values-as/arrays.xml
index 1a044f5..503c13e 100644
--- a/packages/SettingsLib/res/values-as/arrays.xml
+++ b/packages/SettingsLib/res/values-as/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp১৫"</item>
     <item msgid="1963366694959681026">"avrcp১৬"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (ডিফ’ল্ট)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"ছিষ্টেমৰ বাছনি ব্যৱহাৰ কৰক (ডিফ\'ল্ট)"</item>
     <item msgid="4055460186095649420">"এছবিচি"</item>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index 3f85fe3..fa26b9b 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche সক্ষম কৰক"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"ব্লুটুথ AVRCP সংস্কৰণ"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"ব্লুটুথ AVRCP সংস্কৰণ বাছনি কৰক"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"ব্লুটুথ MAP সংস্কৰণ"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"ব্লুটুথ MAP সংস্কৰণ বাছনি কৰক"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"ব্লুটুথ অডিঅ’ ক’ডেক"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ব্লুটুথ অডিঅ\' ক\'ডেকৰ বাছনি\nআৰম্ভ কৰক"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ব্লুটুথ অডিঅ\' ছেম্পল ৰেইট"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ADB/ADTৰ যোগেৰে ইনষ্টল কৰা এপসমূহে কিবা ক্ষতিকাৰক আচৰণ কৰিছে নেকি পৰীক্ষা কৰক।"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"নামহীন ব্লুটুথ ডিভাইচসমূহ (মাত্ৰ MAC ঠিকনাযুক্ত) দেখুওৱা হ\'ব"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"ৰিম\'ট ডিভাইচবিলাকৰ সৈতে ভলিউম সম্পৰ্কীয় সমস্যা, যেনেকৈ অতি উচ্চ ভলিউম বা নিয়ন্ত্ৰণ কৰিবই নোৱাৰা অৱস্থাত ব্লুটুথৰ পূৰ্ণ ভলিউম সুবিধা অক্ষম কৰে।"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"ব্লুটুথ Gabeldorche সুবিধাৰ সমষ্টিটো সক্ষম কৰে।"</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"ব্লুটুথ Gabeldorche সুবিধাৰ সমষ্টিটো সক্ষম কৰে।"</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"স্থানীয় টাৰ্মিনেল"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"স্থানীয় শ্বেল প্ৰৱেশাধিকাৰ দিয়া টাৰ্মিনেল এপ্ সক্ষম কৰক"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP পৰীক্ষণ"</string>
diff --git a/packages/SettingsLib/res/values-az/arrays.xml b/packages/SettingsLib/res/values-az/arrays.xml
index eb81381..005bdf7 100644
--- a/packages/SettingsLib/res/values-az/arrays.xml
+++ b/packages/SettingsLib/res/values-az/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (Defolt)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Sistem Seçimini istifadə edin (Defolt)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 3a1a543..2e80fdc 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche\'ni aktiv edin"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP Versiya"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Bluetooth AVRCP Versiyasını seçin"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetooth MAP Versiyası"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Bluetooth MAP Versiyasını seçin"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth Audio Kodek"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth Audio KodeK\nSeçimini aktiv edin"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth Audio Nümunə Göstəricisi"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ADB/ADT vasitəsi ilə quraşdırılmış tətbiqləri zərərli davranış üzrə yoxlayın."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Adsız Bluetooth cihazları (yalnız MAC ünvanları) göstəriləcək"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Uzaqdan idarə olunan cihazlarda dözülməz yüksək səs həcmi və ya nəzarət çatışmazlığı kimi səs problemləri olduqda Bluetooth mütləq səs həcmi xüsusiyyətini deaktiv edir."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Bluetooth Gabeldorche xüsusiyyətini aktiv edir."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Bluetooth Gabeldorsche funksiyasını aktiv edir."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Yerli terminal"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Yerli örtük girişini təklif edən terminal tətbiqi aktiv edin"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP yoxlanılır"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
index c7b63b3..10c0d6c 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (podrazumevano)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Koristi izbor sistema (podrazumevano)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 02e5e3b..ae5c936 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Omogući Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Verzija Bluetooth AVRCP-a"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Izaberite verziju Bluetooth AVRCP-a"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Verzija Bluetooth MAP-a"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Izaberite verziju Bluetooth MAP-a"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth audio kodek"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Izaberite Bluetooth audio kodek\n"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Brzina uzorkovanja za Bluetooth audio"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Proverava da li su aplikacije instalirane preko ADB-a/ADT-a štetne."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Biće prikazani Bluetooth uređaji bez naziva (samo sa MAC adresama)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Onemogućava glavno podešavanje jačine zvuka na Bluetooth uređaju u slučaju problema sa jačinom zvuka na daljinskim uređajima, kao što su izuzetno velika jačina zvuka ili nedostatak kontrole."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Omogućava grupu Bluetooth Gabeldorche funkcija."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Omogućava grupu Bluetooth Gabeldorsche funkcija."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Lokalni terminal"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Omogući apl. terminala za pristup lokalnom komandnom okruženju"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP provera"</string>
diff --git a/packages/SettingsLib/res/values-be/arrays.xml b/packages/SettingsLib/res/values-be/arrays.xml
index 9eaab6a..e05fd60 100644
--- a/packages/SettingsLib/res/values-be/arrays.xml
+++ b/packages/SettingsLib/res/values-be/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (стандартна)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Выбар сістэмы (стандартны)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 481dfb0..ad201d0 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Уключыць Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Версія Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Выбраць версію Bluetooth AVRCP"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Версія Bluetooth MAP"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Выбраць версію Bluetooth MAP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Кодэк Bluetooth Audio"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Уключыць кодэк Bluetooth Audio\nВыбар"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Частата дыскрэтызацыі Bluetooth Audio"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Праверка бяспекі праграм, усталяваных з дапамогай ADB/ADT."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Прылады Bluetooth будуць паказаны без назваў (толькі MAC-адрасы)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Адключыць функцыю абсалютнага гуку Bluetooth у выпадку праблем з гукам на аддаленых прыладах, напрыклад, пры непрымальна высокай гучнасці або адсутнасці кіравання."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Уключае стос функцый Bluetooth Gabeldorche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Уключае стос функцый Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Лакальны тэрмінал"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Уключэнне прыкладання тэрмінала, якое прапануе доступ да лакальнай абалонкі"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Праверка HDCP"</string>
diff --git a/packages/SettingsLib/res/values-bg/arrays.xml b/packages/SettingsLib/res/values-bg/arrays.xml
index e7976fc..a071baf 100644
--- a/packages/SettingsLib/res/values-bg/arrays.xml
+++ b/packages/SettingsLib/res/values-bg/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (по подразбиране)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Използване на сист. избор (стандартно)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 2a02640..94f78ad 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Активиране на Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Версия на AVRCP за Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Избиране на версия на AVRCP за Bluetooth"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"MAP версия за Bluetooth"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Изберете MAP версия за Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Аудиокодек за Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Задействане на аудиокодек за Bluetooth\nИзбор"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Честота на дискретизация за звука през Bluetooth"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Проверка на инсталираните чрез ADB/ADT приложения за опасно поведение."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Ще бъдат показани устройствата с Bluetooth без имена (само MAC адресите)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Деактивира функцията на Bluetooth за пълна сила на звука в случай на проблеми със звука на отдалечени устройства, като например неприемливо висока сила на звука или липса на управление."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Активира стека на функциите на Bluetooth Gabeldorsche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Активира стека на функциите на Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Локален терминал"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Актив. на прил. за терминал с достъп до локалния команден ред"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Проверка с HDCP"</string>
diff --git a/packages/SettingsLib/res/values-bn/arrays.xml b/packages/SettingsLib/res/values-bn/arrays.xml
index a67b9eb..a131a3b 100644
--- a/packages/SettingsLib/res/values-bn/arrays.xml
+++ b/packages/SettingsLib/res/values-bn/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (ডিফল্ট)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 9bebe41..51719160 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche ফিচার চালু করুন"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"ব্লুটুথ AVRCP ভার্সন"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"ব্লুটুথ AVRCP ভার্সন বেছে নিন"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"ব্লুটুথ MAP ভার্সন"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"ব্লুটুথ MAP ভার্সন বেছে নিন"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"ব্লুটুথ অডিও কোডেক"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ব্লুটুথ অডিও কোডেক ট্রিগার করুন\nএটি বেছে নেওয়া আছে"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ব্লুটুথ অডিওর নমুনা হার"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ক্ষতিকারক ক্রিয়াকলাপ করছে কিনা তার জন্য ADB/ADT মারফত ইনস্টল করা অ্যাপ্লিকেশানগুলি চেক করুন।"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"নামহীন ব্লুটুথ ডিভাইসগুলি দেখানো হবে (শুধুমাত্র MAC অ্যাড্রেস)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"অপ্রত্যাশিত উচ্চ ভলিউম বা নিয়ন্ত্রণের অভাবের মত দূরবর্তী ডিভাইসের ভলিউম সমস্যাগুলির ক্ষেত্রে, ব্লুটুথ চুড়ান্ত ভলিউম বৈশিষ্ট্য অক্ষম করে৷"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"ব্লুটুথ Gabeldorche ফিচার স্ট্যাক চালু করা হয়েছে।"</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"ব্লুটুথ Gabeldorche ফিচার স্ট্যাক চালু করে।"</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"স্থানীয় টার্মিনাল"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"স্থানীয় শেল অ্যাক্সেসের প্রস্তাব করে এমন টার্মিনাল অ্যাপ্লিকেশন সক্ষম করুন"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP পরীক্ষণ"</string>
diff --git a/packages/SettingsLib/res/values-bs/arrays.xml b/packages/SettingsLib/res/values-bs/arrays.xml
index d8b2bcd..6489cef 100644
--- a/packages/SettingsLib/res/values-bs/arrays.xml
+++ b/packages/SettingsLib/res/values-bs/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (Zadano)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Korištenje odabira sistema (zadano)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index f2446ad..f74bcee 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Omogući Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP verzija"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Odaberite Bluetooth AVRCP verziju"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetooth MAP verzija"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Odaberite Bluetooth MAP verziju"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth Audio kodek"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Aktivirajte Bluetooth Audio Codec\nOdabir"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Brzina uzorkovanja za Bluetooth audio"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Provjerava da li se u aplikacijama instaliranim putem ADB-a/ADT-a javlja zlonamjerno ponašanje."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Prikazat će se Bluetooth uređaji bez naziva (samo MAC adrese)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Onemogućava funkciju apsolutne jačine zvuka za Bluetooth u slučaju problema s jačinom zvuka na udaljenim uređajima, kao što je neprihvatljivo glasan zvuk ili nedostatak kontrole."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Omogućava grupisanje funkcije Bluetooth Gabeldorsche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Omogućava grupisanje funkcije Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Lokalni terminal"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Omogući terminalnu aplik. koja nudi pristup lok. kom. okruženju"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP provjera"</string>
diff --git a/packages/SettingsLib/res/values-ca/arrays.xml b/packages/SettingsLib/res/values-ca/arrays.xml
index 600a7ce..950e469 100644
--- a/packages/SettingsLib/res/values-ca/arrays.xml
+++ b/packages/SettingsLib/res/values-ca/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (predeterminada)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Utilitza selecció del sistema (predeterminada)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index e33fd29..1b23ecf 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Activa Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Versió AVRCP de Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Selecciona la versió AVRCP de Bluetooth"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Versió MAP de Bluetooth"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Selecciona la versió MAP de Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Còdec d\'àudio per Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Activa el còdec d\'àudio per Bluetooth\nSelecció"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Freqüència de mostratge d’àudio per Bluetooth"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Comprova les aplicacions instal·lades mitjançant ADB/ADT per detectar comportaments perillosos"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Es mostraran els dispositius Bluetooth sense el nom (només l\'adreça MAC)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Desactiva la funció de volum absolut del Bluetooth en cas que es produeixin problemes de volum amb dispositius remots, com ara un volum massa alt o una manca de control."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Activa el conjunt de funcions de Bluetooth Gabeldorsche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Activa el conjunt de funcions de Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Terminal local"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Activa l\'aplicació de terminal que ofereix accés al shell local"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Comprovació d\'HDCP"</string>
diff --git a/packages/SettingsLib/res/values-cs/arrays.xml b/packages/SettingsLib/res/values-cs/arrays.xml
index e7474a9..16358ee 100644
--- a/packages/SettingsLib/res/values-cs/arrays.xml
+++ b/packages/SettingsLib/res/values-cs/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (výchozí)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Použít systémový výběr (výchozí)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index e787510..22603cc 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Zapnout funkci Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Verze profilu Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Vyberte verzi profilu Bluetooth AVRCP"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Verze MAP pro Bluetooth"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Vyberte verzi MAP pro Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth Audio – kodek"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Spustit zvukový kodek Bluetooth\nVýběr"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth Audio – vzorkovací frekvence"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Kontrolovat škodlivost aplikací nainstalovaných pomocí nástroje ADB/ADT"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Zařízení Bluetooth se budou zobrazovat bez názvů (pouze adresy MAC)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Zakáže funkci absolutní hlasitosti Bluetooth. Zabrání tak problémům s hlasitostí vzdálených zařízení (jako je příliš vysoká hlasitost nebo nemožnost ovládání)."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Zapnout sadu funkcí Bluetooth Gabeldorche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Zapne sadu funkcí Bluetooth Gabeldorche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Místní terminál"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Aktivovat terminálovou aplikaci pro místní přístup k prostředí shell"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Kontrola HDCP"</string>
diff --git a/packages/SettingsLib/res/values-da/arrays.xml b/packages/SettingsLib/res/values-da/arrays.xml
index 0394562..b3ce257 100644
--- a/packages/SettingsLib/res/values-da/arrays.xml
+++ b/packages/SettingsLib/res/values-da/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (standard)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Brug systemvalg (standard)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 4e36e38..bef1855 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Aktivér Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"AVRCP-version for Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Vælg AVRCP-version for Bluetooth"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"MAP-version for Bluetooth"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Vælg MAP-version for Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth-lydcodec"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Udløs codec for Bluetooth-lyd\nValg"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Eksempelfrekvens for Bluetooth-lyd"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Tjek apps, der er installeret via ADB/ADT, for skadelig adfærd."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth-enheder uden navne (kun MAC-adresser) vises"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Deaktiverer funktionen til absolut lydstyrke via Bluetooth i tilfælde af problemer med lydstyrken på eksterne enheder, f.eks. uacceptabel høj lyd eller manglende kontrol."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Aktiverer funktioner fra Bluetooth Gabeldorche"</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Aktiverer funktioner fra Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Lokal terminal"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Aktivér terminalappen, der giver lokal shell-adgang"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP-kontrol"</string>
diff --git a/packages/SettingsLib/res/values-de/arrays.xml b/packages/SettingsLib/res/values-de/arrays.xml
index d7d3226..fdd799c 100644
--- a/packages/SettingsLib/res/values-de/arrays.xml
+++ b/packages/SettingsLib/res/values-de/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (Standard)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Systemauswahl verwenden (Standard)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 6369906..c8c97bd 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Bluetooth-Gabeldorsche aktivieren"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP-Version"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Bluetooth AVRCP-Version auswählen"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetooth MAP-Version"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Bluetooth MAP-Version auswählen"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth-Audio-Codec"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth-Audio-Codec auslösen\nAuswahl"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth-Audio-Abtastrate"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Über ADB/ADT installierte Apps werden auf schädliches Verhalten geprüft"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth-Geräte werden ohne Namen und nur mit ihren MAC-Adressen angezeigt"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Deaktiviert die Funktion \"Absolute Lautstärkeregelung\" für Bluetooth-Geräte, falls auf Remote-Geräten Probleme mit der Lautstärke auftreten, wie beispielsweise übermäßig laute Wiedergabe oder fehlende Steuerungsmöglichkeiten."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Aktiviert das Bluetooth-Gabeldorsche-Funktionspaket."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Aktiviert das Bluetooth-Gabeldorsche-Funktionspaket."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Lokales Terminal"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Terminal-App mit Zugriff auf lokale Shell aktivieren"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP-Prüfung"</string>
diff --git a/packages/SettingsLib/res/values-el/arrays.xml b/packages/SettingsLib/res/values-el/arrays.xml
index 5c4ef13..79f631f 100644
--- a/packages/SettingsLib/res/values-el/arrays.xml
+++ b/packages/SettingsLib/res/values-el/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (Προεπιλογή)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Χρήση επιλογής συστήματος (Προεπιλογή)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 194324f..371075c 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Ενεργοποίηση Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Έκδοση AVRCP Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Επιλογή έκδοσης AVRCP Bluetooth"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Έκδοση MAP Bluetooth"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Επιλογή έκδοσης MAP Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Κωδικοποιητής ήχου Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Ενεργοποίηση κωδικοποιητή ήχου Bluetooth\nΕπιλογή"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Ρυθμός δειγματοληψίας ήχου Bluetooth"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Έλεγχος εφαρμογών που έχουν εγκατασταθεί μέσω ADB/ADT για επιβλαβή συμπεριφορά."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Θα εμφανιστούν οι συσκευές Bluetooth χωρίς ονόματα (μόνο διευθύνσεις MAC)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Απενεργοποιεί τη δυνατότητα απόλυτης έντασης του Bluetooth σε περίπτωση προβλημάτων έντασης με απομακρυσμένες συσκευές, όπως όταν υπάρχει μη αποδεκτά υψηλή ένταση ή απουσία ελέγχου."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Ενεργοποιεί τη στοίβα λειτουργιών Bluetooth Gabeldorche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Ενεργοποιεί τη στοίβα λειτουργιών Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Τοπική τερματική εφαρμογή"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Ενεργοπ.τερμ.εφαρμογής που προσφέρει πρόσβαση στο τοπικό κέλυφος"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Έλεγχος HDCP"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/arrays.xml b/packages/SettingsLib/res/values-en-rAU/arrays.xml
index ae1fb78..97e598e 100644
--- a/packages/SettingsLib/res/values-en-rAU/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rAU/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (Default)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Use system selection (default)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 92ed8e5..b314d17 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Enable Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP version"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Select Bluetooth AVRCP Version"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetooth MAP version"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Select Bluetooth MAP version"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth audio codec"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Trigger Bluetooth Audio Codec\nSelection"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth audio sample rate"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Check apps installed via ADB/ADT for harmful behaviour."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth devices without names (MAC addresses only) will be displayed"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Disables the Bluetooth absolute volume feature in case of volume issues with remote devices such as unacceptably loud volume or lack of control."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Enables the Bluetooth Gabeldorsche feature stack."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Enables the Bluetooth Gabeldorsche feature stack."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Local terminal"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Enable terminal app that offers local shell access"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP checking"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/arrays.xml b/packages/SettingsLib/res/values-en-rCA/arrays.xml
index ae1fb78..97e598e 100644
--- a/packages/SettingsLib/res/values-en-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rCA/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (Default)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Use system selection (default)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 92ed8e5..b314d17 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Enable Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP version"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Select Bluetooth AVRCP Version"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetooth MAP version"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Select Bluetooth MAP version"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth audio codec"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Trigger Bluetooth Audio Codec\nSelection"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth audio sample rate"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Check apps installed via ADB/ADT for harmful behaviour."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth devices without names (MAC addresses only) will be displayed"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Disables the Bluetooth absolute volume feature in case of volume issues with remote devices such as unacceptably loud volume or lack of control."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Enables the Bluetooth Gabeldorsche feature stack."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Enables the Bluetooth Gabeldorsche feature stack."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Local terminal"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Enable terminal app that offers local shell access"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP checking"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/arrays.xml b/packages/SettingsLib/res/values-en-rGB/arrays.xml
index ae1fb78..97e598e 100644
--- a/packages/SettingsLib/res/values-en-rGB/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rGB/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (Default)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Use system selection (default)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 92ed8e5..b314d17 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Enable Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP version"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Select Bluetooth AVRCP Version"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetooth MAP version"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Select Bluetooth MAP version"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth audio codec"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Trigger Bluetooth Audio Codec\nSelection"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth audio sample rate"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Check apps installed via ADB/ADT for harmful behaviour."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth devices without names (MAC addresses only) will be displayed"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Disables the Bluetooth absolute volume feature in case of volume issues with remote devices such as unacceptably loud volume or lack of control."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Enables the Bluetooth Gabeldorsche feature stack."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Enables the Bluetooth Gabeldorsche feature stack."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Local terminal"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Enable terminal app that offers local shell access"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP checking"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/arrays.xml b/packages/SettingsLib/res/values-en-rIN/arrays.xml
index ae1fb78..97e598e 100644
--- a/packages/SettingsLib/res/values-en-rIN/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rIN/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (Default)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Use system selection (default)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 92ed8e5..b314d17 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Enable Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP version"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Select Bluetooth AVRCP Version"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetooth MAP version"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Select Bluetooth MAP version"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth audio codec"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Trigger Bluetooth Audio Codec\nSelection"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth audio sample rate"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Check apps installed via ADB/ADT for harmful behaviour."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth devices without names (MAC addresses only) will be displayed"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Disables the Bluetooth absolute volume feature in case of volume issues with remote devices such as unacceptably loud volume or lack of control."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Enables the Bluetooth Gabeldorsche feature stack."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Enables the Bluetooth Gabeldorsche feature stack."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Local terminal"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Enable terminal app that offers local shell access"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP checking"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/arrays.xml b/packages/SettingsLib/res/values-en-rXC/arrays.xml
index af5d7f3..eca7c75 100644
--- a/packages/SettingsLib/res/values-en-rXC/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rXC/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‎‏‎‎‎‎‏‏‎‎‎‏‎‎‏‏‏‎‎‏‏‎‎‏‎‎‏‏‏‎‏‏‎‏‏‎‏‎‎‏‏‎‏‏‏‏‏‎‎‎‏‎‏‎‎‏‎‏‎avrcp15‎‏‎‎‏‎"</item>
     <item msgid="1963366694959681026">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‏‏‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‏‏‎‎‏‏‎‏‏‎‏‎‏‎‎‎‎‏‏‏‎‎‏‏‏‏‎‎‎‏‏‏‎‎‎‎‎‎‎‏‎‎avrcp16‎‏‎‎‏‎"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‎‎‏‏‎‎‎‏‏‎‏‏‏‎‎‏‎‏‏‎‎‎‎‎‎‏‏‎‎‎‏‎‏‏‎‏‏‎MAP 1.2 (Default)‎‏‎‎‏‎"</item>
+    <item msgid="6817922176194686449">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‎‏‏‏‏‎‎‎‏‎‎‎‎‎‎‎‎‏‏‎‎‎‏‎‏‎‏‎‏‎‎‏‎‏‎‏‏‏‏‎‏‎‏‏‎‏‏‏‏‏‎‎‎‏‎MAP 1.3‎‏‎‎‏‎"</item>
+    <item msgid="3423518690032737851">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‏‏‏‏‎‎‎‎‎‏‎‏‏‎‎‏‎‎‎‎‎‎‏‏‏‎‎‎‎‏‎‏‎‎‏‎‏‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‎‏‏‏‎‏‏‎MAP 1.4‎‏‎‎‏‎"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‎‎‎‏‎‏‎‎‏‏‎‏‎‏‏‎‎‏‎‏‎‏‎‏‏‎‎‏‏‏‎‏‎‎‎‏‏‏‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‏‎map12‎‏‎‎‏‎"</item>
+    <item msgid="7073042887003102964">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‏‎‏‎‎‎‎‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‎‏‎‎‎map13‎‏‎‎‏‎"</item>
+    <item msgid="8147982633566548515">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‏‎‎‏‏‎‏‏‏‎‎‏‏‎‎‎‎‏‎‎‏‎‎‎‎‏‏‎‏‏‏‎‎‏‎‎‏‎‎‏‏‎‎‏‎‎‎‏‎‎‎‏‏‎map14‎‏‎‎‏‎"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‎‏‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‎‏‏‏‎‏‎‎‏‎‎‏‏‏‎‎‎‏‎‏‏‏‎‎‎‎‏‏‎‏‎‏‏‏‎‏‏‎Use System Selection (Default)‎‏‎‎‏‎"</item>
     <item msgid="4055460186095649420">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‎‎‏‏‏‏‏‏‎‎‎‏‏‏‎‎‎‏‏‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‎‎‎‏‎‎‎‎‎‏‎‏‎‎‎‏‏‎‎‎SBC‎‏‎‎‏‎"</item>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 9813efd..95944dc 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‏‎‎‏‏‎‏‏‎‎‎‏‏‎‏‎‎‏‏‏‎‏‎‏‎‎‏‎‏‏‎‎‎‏‏‎‏‏‎‎‏‏‎‏‎‏‏‎‎‎‎Enable Gabeldorsche‎‏‎‎‏‎"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‏‏‏‎‏‏‏‏‎‏‎‎‏‎‏‎‏‏‏‏‎‏‎‎‎‏‎‎‎‎‎‎‏‏‏‎‎‎‎‎‎‏‏‏‏‎‎‎‎‎‏‏‏‏‎‏‏‏‎Bluetooth AVRCP Version‎‏‎‎‏‎"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‎‎‏‎‏‏‏‎‏‏‏‏‎‎‎‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‎‎‎‏‎‎‎‏‏‎‎‎‎‏‎‏‏‎‎‎‎‎‏‎Select Bluetooth AVRCP Version‎‏‎‎‏‎"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‏‏‏‏‎‏‎‎‏‏‎‏‏‏‎‏‎‎‏‎‎‏‏‏‏‎‎‎‎‎‏‏‎‎‏‏‏‎‎‎‎‎‎‎‎‏‎‏‏‏‏‎‎‏‎‏‏‏‏‏‎Bluetooth MAP Version‎‏‎‎‏‎"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‎‏‎‏‏‎‎‏‎‎‏‎‏‏‏‏‎‎‎‏‎‏‎‎‏‎‏‏‏‏‎‏‎‎‎‎‎‎‎‎‏‎‏‎‎‎‎‏‏‎‏‏‎‎‎Select Bluetooth MAP Version‎‏‎‎‏‎"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‎‏‎‎‏‏‎‏‏‎‎‎‏‏‎‎‎‎‎‎‏‏‏‏‎‎‏‎‏‏‎‎‎‎‏‎‏‎‏‎‎‎‏‎‏‏‎‏‏‎‏‏‏‎‏‏‏‎‎Bluetooth Audio Codec‎‏‎‎‏‎"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‏‎‏‎‏‏‎‎‏‏‏‎‏‎‎‎‎‏‏‎‎‎‏‎‏‎‏‎‎‏‏‏‏‎‎‎‏‏‎‏‎‏‏‏‏‏‎‎‏‎‎‏‎Trigger Bluetooth Audio Codec‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Selection‎‏‎‎‏‎"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‏‏‎‏‏‎‎‎‏‏‏‏‎‎‎‎‎‎‎‏‏‎‎‏‏‎‏‎‎‏‏‎‎‏‏‏‎‏‎‎‏‎‎‏‏‎‏‏‏‏‏‏‎Bluetooth Audio Sample Rate‎‏‎‎‏‎"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‏‎‎‏‎‎‏‎‏‎‎‎‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‏‏‎‏‎‏‎‎‎‎‎‎‏‏‏‎‏‎‎‎‏‎‎‏‏‎‏‏‏‏‏‎Check apps installed via ADB/ADT for harmful behavior.‎‏‎‎‏‎"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‎‏‏‎‏‎‏‏‎‏‎‎‎‏‎‏‎‏‏‏‏‎‎‎‏‎‏‎‎‏‏‎‎‏‏‏‎‏‏‏‏‎‎‏‎‏‏‏‎‎‎‏‎‏‎‏‏‎Bluetooth devices without names (MAC addresses only) will be displayed‎‏‎‎‏‎"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‏‏‏‏‎‏‎‏‏‏‏‏‎‏‏‎‎‎‎‏‎‎‎‎‎‎‏‏‎‏‏‏‏‎‎‏‎‎‎‏‏‏‎‎‎‎‎‎‏‏‎‎‏‎‎‎‎‏‎Disables the Bluetooth absolute volume feature in case of volume issues with remote devices such as unacceptably loud volume or lack of control.‎‏‎‎‏‎"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‏‎‎‏‏‏‏‎‏‎‎‎‎‏‏‎‎‏‏‎‎‏‎‎‏‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‎‏‏‏‏‎‏‏‏‎‏‏‎‎Enables the Bluetooth Gabeldorche feature stack.‎‏‎‎‏‎"</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‎‎‏‏‎‏‎‏‏‏‎‎‏‏‎‏‎‎‏‏‏‏‏‎‎‏‎‎‎‏‏‎‏‎‏‎Enables the Bluetooth Gabeldorsche feature stack.‎‏‎‎‏‎"</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‎‏‎‎‏‏‎‏‏‏‏‏‏‎‏‎‎‏‏‎‏‎‏‏‏‎‎‎‏‎‏‎‏‏‎‎‎‏‏‏‏‏‎‎‎‎‏‏‏‎‏‎‏‎‎‏‏‎‎Local terminal‎‏‎‎‏‎"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‎‎‏‏‎‏‏‏‎‏‎‎‎‏‏‎‎‎‏‏‎‏‎‏‎‏‏‎‎‎‎‎‎‏‏‎‎‎‎‎‏‏‎‏‏‎‏‎‏‏‏‏‏‎‏‎‎‎Enable terminal app that offers local shell access‎‏‎‎‏‎"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‏‏‏‏‎‎‏‎‏‏‎‏‎‎‎‏‎‏‏‏‎‏‏‏‏‎‎‏‎‏‎‎‏‎‏‎‎‏‏‎‏‎‏‏‎‎‎‏‏‏‎‏‏‏‎‎‏‎‎HDCP checking‎‏‎‎‏‎"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/arrays.xml b/packages/SettingsLib/res/values-es-rUS/arrays.xml
index d37ffb7..ad58235 100644
--- a/packages/SettingsLib/res/values-es-rUS/arrays.xml
+++ b/packages/SettingsLib/res/values-es-rUS/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (predeterminado)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Usar selección del sistema (predeterminado)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 8899c07..c6dfdd3 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Habilitar Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Versión de AVRCP del Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Selecciona la versión de AVRCP del Bluetooth"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Versión de MAP de Bluetooth"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Seleccionar versión de MAP de Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Códec del audio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Activar el códec de audio por Bluetooth\nSelección"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Frecuencia de muestreo del audio Bluetooth"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Comprobar que las aplicaciones instaladas mediante ADB/ADT no ocasionen daños"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Se mostrarán los dispositivos Bluetooth sin nombre (solo direcciones MAC)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Inhabilita la función de volumen absoluto de Bluetooth si se producen problemas de volumen con dispositivos remotos (por ejemplo, volumen demasiado alto o falta de control)."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Habilita la pila de funciones de Bluetooth Gabeldorsche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Habilita la pila de funciones de Bluetooth Gabeldorsche"</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Terminal local"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Habilitar aplicac. de terminal que ofrece acceso al shell local"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Comprobación HDCP"</string>
diff --git a/packages/SettingsLib/res/values-es/arrays.xml b/packages/SettingsLib/res/values-es/arrays.xml
index 04d4b2d..a403e3e6 100644
--- a/packages/SettingsLib/res/values-es/arrays.xml
+++ b/packages/SettingsLib/res/values-es/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (predeterminado)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Usar preferencia del sistema (predeterminado)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 83ae2df..ba4a9ff 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Habilitar Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Versión AVRCP de Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Selecciona la versión AVRCP de Bluetooth"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Versión de MAP de Bluetooth"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Seleccionar versión de MAP de Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Códec de audio de Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Activar el códec de audio por Bluetooth\nSelección"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Frecuencia de muestreo de audio de Bluetooth"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Comprobar las aplicaciones instaladas mediante ADB/ADT para detectar comportamientos dañinos"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Mostrar dispositivos Bluetooth sin nombre (solo direcciones MAC)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Inhabilitar la función de volumen absoluto de Bluetooth si se producen problemas de volumen con dispositivos remotos (por ejemplo, volumen demasiado alto o falta de control)"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Habilita la pila de funciones de Bluetooth Gabeldorsche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Habilita la pila de funciones de Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Terminal local"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Habilitar aplicación de terminal que ofrece acceso a shell local"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Comprobación de HDCP"</string>
diff --git a/packages/SettingsLib/res/values-et/arrays.xml b/packages/SettingsLib/res/values-et/arrays.xml
index 14a68b0..eb5f347 100644
--- a/packages/SettingsLib/res/values-et/arrays.xml
+++ b/packages/SettingsLib/res/values-et/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (vaikeseade)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Süsteemi valiku kasutamine (vaikeseade)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 297e965..df3b792 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Luba Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetoothi AVRCP versioon"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Valige Bluetoothi AVRCP versioon"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetoothi MAP-i versioon"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Bluetoothi MAP-i versiooni valimine"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetoothi heli kodek"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetoothi helikodeki käivitamine\nValik"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetoothi heli diskreetimissagedus"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Kontrolli, kas ADB/ADT-ga installitud rakendused on ohtlikud."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Kuvatakse ilma nimedeta (ainult MAC-aadressidega) Bluetoothi seadmed"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Keelatakse Bluetoothi absoluutse helitugevuse funktsioon, kui kaugseadmetega on helitugevuse probleeme (nt liiga vali heli või juhitavuse puudumine)."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Lubab Bluetoothi Gabeldorche\'i funktsiooni virnastamise."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Lubab Bluetooth Gabeldorsche\'i funktsiooni virnastamise."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Kohalik terminal"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Luba kohalikku turvalist juurdepääsu pakkuv terminalirakendus"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP-kontrollimine"</string>
diff --git a/packages/SettingsLib/res/values-eu/arrays.xml b/packages/SettingsLib/res/values-eu/arrays.xml
index e87413c..30ac525f7 100644
--- a/packages/SettingsLib/res/values-eu/arrays.xml
+++ b/packages/SettingsLib/res/values-eu/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"1.2 MAPa (lehenetsia)"</item>
+    <item msgid="6817922176194686449">"1.3 MAPa"</item>
+    <item msgid="3423518690032737851">"1.4 MAPa"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Erabili sistema-hautapena (lehenetsia)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 5b84b10..fcb320f 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gaitu Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP bertsioa"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Hautatu Bluetooth AVRCP bertsioa"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetooth MAParen bertsioa"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Hautatu Bluetooth MAParen bertsioa"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth bidezko audioaren kodeka"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Abiarazi Bluetooth bidezko audio-kodeka\nHautapena"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth bidezko audioaren lagin-abiadura"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Egiaztatu ADB/ADT bidez instalatutako aplikazioak portaera kaltegarriak atzemateko"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth gailuak izenik gabe (MAC helbideak soilik) erakutsiko dira"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Bluetooth bidezko bolumen absolutuaren eginbidea desgaitu egiten du urruneko gailuetan arazoak hautematen badira; esaterako, bolumena ozenegia bada edo ezin bada kontrolatu"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Bluetooth Gabeldorsche eginbide sorta gaitzen du."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Bluetooth Gabeldorsche eginbide sorta gaitzen du."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Tokiko terminala"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Gaitu tokiko shell-sarbidea duen terminal-aplikazioa"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP egiaztapena"</string>
diff --git a/packages/SettingsLib/res/values-fa/arrays.xml b/packages/SettingsLib/res/values-fa/arrays.xml
index ba56d24..3b05075 100644
--- a/packages/SettingsLib/res/values-fa/arrays.xml
+++ b/packages/SettingsLib/res/values-fa/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"‏MAP نسخه ۱.۲ (پیش‌فرض)"</item>
+    <item msgid="6817922176194686449">"‏MAP نسخه ۱.۳"</item>
+    <item msgid="3423518690032737851">"‏MAP نسخه ۱.۴"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"استفاده از انتخاب سیستم (پیش‌فرض)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 61fe37a..261a438 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"‏فعال کردن Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"‏نسخه AVRCP بلوتوث"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"‏انتخاب نسخه AVRCP بلوتوث"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"‏نسخه MAP بلوتوث"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"‏انتخاب نسخه MAP بلوتوث"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"کدک بلوتوث صوتی"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"راه‌اندازی کدک صوتی بلوتوثی\nانتخاب"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"سرعت نمونه بلوتوث صوتی"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"‏برنامه‌های نصب‌شده ازطریق ADB/ADT را ازنظر رفتار مخاطره‌آمیز بررسی کنید."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"‏دستگاه‌های بلوتوث بدون نام (فقط نشانی‌های MAC) نشان داده خواهند شد"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"درصورت وجود مشکل در صدا با دستگاه‌های راه دور مثل صدای بلند ناخوشایند یا عدم کنترل صدا، ویژگی میزان صدای کامل بلوتوث را غیرفعال کنید."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"‏دسته ویژگی Gabeldorche، بلوتوث را فعال می‌کند."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"‏دسته ویژگی Gabeldorsche، بلوتوث را فعال می‌کند."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"ترمینال محلی"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"فعال کردن ترمینال برنامه‌ کاربردی که دسترسی به برنامه محلی را پیشنهاد می‌کند"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"‏بررسی HDCP"</string>
diff --git a/packages/SettingsLib/res/values-fi/arrays.xml b/packages/SettingsLib/res/values-fi/arrays.xml
index 79a46ba..c899d9c 100644
--- a/packages/SettingsLib/res/values-fi/arrays.xml
+++ b/packages/SettingsLib/res/values-fi/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (oletus)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Käytä järjestelmän valintaa (oletus)."</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 7e8b160..4ccf430 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Ota Gabeldorsche käyttöön"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetoothin AVRCP-versio"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Valitse Bluetoothin AVRCP-versio"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetoothin MAP-versio"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Valitse Bluetoothin MAP-versio"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth-äänen koodekki"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Käynnistä Bluetooth-äänipakkaus\nValinta"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth-ääninäytteen siirtonopeus"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Tarkista ADB:n/ADT:n kautta asennetut sovellukset haitallisen toiminnan varalta."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Näytetään Bluetooth-laitteet, joilla ei ole nimiä (vain MAC-osoitteet)."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Bluetoothin yleinen äänenvoimakkuuden säätö poistetaan käytöstä ongelmien välttämiseksi esimerkiksi silloin, kun laitteen äänenvoimakkuus on liian kova tai sitä ei voi säätää."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Bluetoothin Gabeldorche-ominaisuuspino tulee käyttöön."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Bluetoothin Gabeldorsche-ominaisuuspino otetaan käyttöön."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Paikallinen pääte"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Ota käyttöön päätesov. joka mahdollistaa paikall. liittymäkäytön"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP-tarkistus"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/arrays.xml b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
index 3ee3209..02b374a 100644
--- a/packages/SettingsLib/res/values-fr-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (valeur par défaut)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Utiliser sélect. du système (par défaut)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index d21eeef..84a9797 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Activer le Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Version du profil Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Sélectionner la version du profil Bluetooth AVRCP"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Version du profil Bluetooth MAP"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Sélectionner la version du profil Bluetooth MAP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Codec audio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Déclencher le codec audio Bluetooth\nSélection"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Taux d\'échantillonnage pour l\'audio Bluetooth"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Vérifier que les applications installées par ADB/ADT ne présentent pas de comportement dangereux."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Les appareils Bluetooth sans nom (adresses MAC seulement) seront affichés"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Désactive la fonctionnalité de volume absolu par Bluetooth en cas de problème de volume sur les appareils à distance, par exemple si le volume est trop élevé ou s\'il ne peut pas être contrôlé."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Active la pile de la fonctionnalité Bluetooth Gabeldorche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Active la pile de la fonctionnalité Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Terminal local"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Activer l\'application Terminal permettant l\'accès au shell local"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Vérification HDCP"</string>
diff --git a/packages/SettingsLib/res/values-fr/arrays.xml b/packages/SettingsLib/res/values-fr/arrays.xml
index e23fc6a..9ccaf09 100644
--- a/packages/SettingsLib/res/values-fr/arrays.xml
+++ b/packages/SettingsLib/res/values-fr/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (valeur par défaut)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Utiliser la sélection du système (par défaut)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 23dd5a8..030a7f9 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Activer Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Version Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Sélectionner la version Bluetooth AVRCP"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Version Bluetooth MAP"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Sélectionner la version Bluetooth MAP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Codec audio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Critère pour déclencher la sélection du codec audio\nBluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Taux d\'échantillonnage audio Bluetooth"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Vérifier que les applications installées par ADB/ADT ne présentent pas de comportement dangereux"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Les appareils Bluetooth sans nom (adresses MAC seulement) seront affichés"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Désactive la fonctionnalité de volume absolu du Bluetooth en cas de problème de volume sur les appareils à distance, par exemple si le volume est trop élevé ou s\'il ne peut pas être contrôlé"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Active la pile de fonctionnalités Bluetooth Gabeldorsche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Active la pile de fonctionnalités Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Terminal local"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Activer l\'application Terminal permettant l\'accès au shell local"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Vérification HDCP"</string>
diff --git a/packages/SettingsLib/res/values-gl/arrays.xml b/packages/SettingsLib/res/values-gl/arrays.xml
index c0a5a80..5fad943 100644
--- a/packages/SettingsLib/res/values-gl/arrays.xml
+++ b/packages/SettingsLib/res/values-gl/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (predeterminada)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Usar selección do sistema (predeterminado)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index c8f6f81..af033cf 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Activar Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Versión de Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Selecciona a versión de Bluetooth AVRCP"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Versión de MAP de Bluetooth"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Selecciona a versión de MAP de Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Códec de audio por Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Activar códec de audio por Bluetooth\nSelección"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Taxa de mostra de audio por Bluetooth"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Comproba as aplicacións instaladas a través de ADB/ADT para detectar comportamento perigoso"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Mostraranse dispositivos Bluetooth sen nomes (só enderezos MAC)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Desactiva a función do volume absoluto do Bluetooth en caso de que se produzan problemas de volume cos dispositivos remotos, como volume demasiado alto ou falta de control"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Activa a pilla de funcións Bluetooth Gabeldorche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Activa o conxunto de funcións de Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Terminal local"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Activa a aplicación terminal que ofrece acceso ao shell local"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Comprobación HDCP"</string>
diff --git a/packages/SettingsLib/res/values-gu/arrays.xml b/packages/SettingsLib/res/values-gu/arrays.xml
index 75c904d..8e28b8b 100644
--- a/packages/SettingsLib/res/values-gu/arrays.xml
+++ b/packages/SettingsLib/res/values-gu/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (ડિફૉલ્ટ)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index d274674..87fd876 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche ચાલુ કરો"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"બ્લૂટૂથ AVRCP સંસ્કરણ"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"બ્લૂટૂથ AVRCP સંસ્કરણ પસંદ કરો"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"બ્લૂટૂથ MAP વર્ઝન"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"બ્લૂટૂથ MAP વર્ઝન પસંદ કરો"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"બ્લૂટૂથ ઑડિઓ કોડેક"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"બ્લૂટૂથ ઑડિઓ કોડેક\nપસંદગી ટ્રિગર કરો"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"બ્લૂટૂથ ઑડિઓ નમૂના દર"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"હાનિકારક વર્તણૂંક માટે ADB/ADT મારફતે ઇન્સ્ટોલ કરવામાં આવેલી ઍપ્લિકેશનો તપાસો."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"નામ વગરના (ફક્ત MAC ઍડ્રેસવાળા) બ્લૂટૂથ ઉપકરણો બતાવવામાં આવશે"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"રિમોટ ઉપકરણોમાં વધુ પડતું ઊંચું વૉલ્યૂમ અથવા નિયંત્રણની કમી જેવી વૉલ્યૂમની સમસ્યાઓની સ્થિતિમાં બ્લૂટૂથ ચોક્કસ વૉલ્યૂમ સુવિધાને અક્ષમ કરે છે."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"બ્લૂટૂથ Gabeldorche સુવિધા સ્ટૅક ચાલુ કરે છે."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"બ્લૂટૂથ Gabeldorsche સુવિધાનું સ્ટૅક ચાલુ કરે છે."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"સ્થાનિક ટર્મિનલ"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"સ્થાનિક શેલ અ‍ૅક્સેસની ઑફર કરતી ટર્મિનલ એપ્લિકેશનને સક્ષમ કરો"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP તપાસણી"</string>
diff --git a/packages/SettingsLib/res/values-hi/arrays.xml b/packages/SettingsLib/res/values-hi/arrays.xml
index ffaf80a..3c744e1 100644
--- a/packages/SettingsLib/res/values-hi/arrays.xml
+++ b/packages/SettingsLib/res/values-hi/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (डिफ़ॉल्ट)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"सिस्टम से चुने जाने का उपयोग करें (डिफ़ॉल्ट)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index d0307ec..02b5c96 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche चालू करें"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"ब्लूटूथ एवीआरसीपी वर्शन"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"ब्लूटूथ AVRCP वर्शन चुनें"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"ब्लूटूथ का MAP वर्शन"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"ब्लूटूथ का MAP वर्शन चुनें"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"ब्लूटूथ ऑडियो कोडेक"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ब्लूटूथ ऑडियो कोडेक का\nविकल्प चालू करें"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ब्लूटूथ ऑडियो नमूना दर"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"नुकसानदेह व्यवहार के लिए ADB/ADT से इंस्टॉल किए गए ऐप्लिकेशन जाँचें."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"बिना नाम वाले ब्लूटूथ डिवाइस (केवल MAC पते वाले) दिखाए जाएंगे"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"दूर के डिवाइस पर आवाज़ बहुत बढ़ जाने या उससे नियंत्रण हटने जैसी समस्याएं होने पर, यह ब्लूटूथ के ज़रिए आवाज़ के नियंत्रण की सुविधा रोक देता है."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"ब्लूटूथ Gabeldorsche सुविधा का स्टैक चालू करें."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"ब्लूटूथ सेटिंग में Gabeldorsche सुविधा को चालू करता है."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"स्थानीय टर्मिनल"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"लोकल शेल तक पहुंचने की सुविधा देने वाले टर्मिनल ऐप को चालू करें"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"एचडीसीपी जाँच"</string>
diff --git a/packages/SettingsLib/res/values-hr/arrays.xml b/packages/SettingsLib/res/values-hr/arrays.xml
index ec979f6..c573e6c 100644
--- a/packages/SettingsLib/res/values-hr/arrays.xml
+++ b/packages/SettingsLib/res/values-hr/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (zadano)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Upotreba odabira sustava (zadano)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 84adcaa..598cfe2 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Omogući Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Verzija AVRCP-a za Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Odaberite verziju AVRCP-a za Bluetooth"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Verzija MAP-a za Bluetooth"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Odaberite verziju MAP-a za Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Kodek za Bluetooth Audio"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Pokreni odabir kodeka za Bluetooth\nAudio"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Brzina uzorka za Bluetooth Audio"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Provjerite uzrokuju li aplikacije instalirane putem ADB-a/ADT-a poteškoće"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Prikazivat će se Bluetooth uređaji bez naziva (samo MAC adrese)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Onemogućuje Bluetoothovu značajku apsolutne glasnoće ako udaljeni uređaji imaju poteškoća sa zvukom, kao što su neprihvatljiva glasnoća ili nepostojanje kontrole"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Omogućuje nizove značajke Bluetooth Gabeldorche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Omogućuje nizove značajke Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Lokalni terminal"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Omogući aplikaciju terminala koja nudi pristup lokalnoj ovojnici"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP provjera"</string>
diff --git a/packages/SettingsLib/res/values-hu/arrays.xml b/packages/SettingsLib/res/values-hu/arrays.xml
index 64d92e4..608a9e03 100644
--- a/packages/SettingsLib/res/values-hu/arrays.xml
+++ b/packages/SettingsLib/res/values-hu/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (Alapértelmezett)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Rendszerérték (alapértelmezett)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index cb87e56..d970c73 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"A Gabeldorsche engedélyezése"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"A Bluetooth AVRCP-verziója"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"A Bluetooth AVRCP-verziójának kiválasztása"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"A Bluetooth MAP-verziója"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"A Bluetooth MAP-verziójának kiválasztása"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth hang – Kodek"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth-hangkodek aktiválása\nKiválasztás"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth hang – mintavételezési gyakoriság"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Az ADB/ADT útján telepített alkalmazások ellenőrzése kártékony viselkedésre."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Név nélküli Bluetooth-eszközök jelennek meg (csak MAC-címekkel)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Letiltja a Bluetooth abszolút hangerő funkcióját a távoli eszközökkel kapcsolatos hangerőproblémák – például elfogadhatatlanul magas vagy nem vezérelhető hangerő – esetén."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Engedélyezi a Bluetooth Gabeldorche funkcióit."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Engedélyezi a Bluetooth Gabeldorsche funkcióit."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Helyi végpont"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Végalkalmazás engedélyezése a helyi rendszerhéj eléréséhez"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP ellenőrzés"</string>
diff --git a/packages/SettingsLib/res/values-hy/arrays.xml b/packages/SettingsLib/res/values-hy/arrays.xml
index b1226f4..a2de6df 100644
--- a/packages/SettingsLib/res/values-hy/arrays.xml
+++ b/packages/SettingsLib/res/values-hy/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (կանխադրված)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Օգտագործել համակարգի կարգավորումը (կանխադրված)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 6c30d4e..9086934 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Միացնել Gabeldorsche-ը"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP տարբերակը"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Ընտրել Bluetooth AVRCP տարբերակը"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetooth MAP-ի տարբերակ"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Ընտրել Bluetooth MAP-ի տարբերակը"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth աուդիո կոդեկ"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Գործարկել Bluetooth աուդիո կոդեկը\nԸնտրություն"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth աուդիոյի ընդհատավորման հաճախականությունը"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Ստուգել հավելվածների անվտանգությունը ADB/ADT-ի միջոցով տեղադրված լինելու դեպքում։"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth սարքերը կցուցադրվեն առանց անունների (միայն MAC հասցեները)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Կասեցնում է Bluetooth-ի ձայնի բացարձակ ուժգնության գործառույթը՝ հեռավոր սարքերի հետ ձայնի ուժգնությանը վերաբերող խնդիրներ ունենալու դեպքում (օրինակ՝ երբ ձայնի ուժգնությունն անընդունելի է կամ դրա կառավարումը հնարավոր չէ):"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Միացնել Bluetooth Gabeldorche գործառույթի զտիչը"</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Միացնել Bluetooth Gabeldorsche գործառույթի զտիչը"</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Տեղային տերմինալ"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Միացնել տերմինալային հավելվածը, որն առաջարկում է մուտք տեղային խեցի"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP ստուգում"</string>
diff --git a/packages/SettingsLib/res/values-in/arrays.xml b/packages/SettingsLib/res/values-in/arrays.xml
index 9d2528a..e73febc 100644
--- a/packages/SettingsLib/res/values-in/arrays.xml
+++ b/packages/SettingsLib/res/values-in/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (Default)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Gunakan Pilihan Sistem (Default)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 654c06c..3c1504c 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Aktifkan Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Versi AVRCP Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Pilih Versi AVRCP Bluetooth"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Versi MAP Bluetooth"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Pilih Versi Map Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Codec Audio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Aktifkan Codec Audio Bluetooth\nPilihan"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Frekuensi Sampel Audio Bluetooth"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Periksa perilaku membahayakan dalam aplikasi yang terpasang melalui ADB/ADT."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Perangkat Bluetooth tanpa nama (hanya alamat MAC) akan ditampilkan"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Menonaktifkan fitur volume absolut Bluetooth jika ada masalah volume dengan perangkat jarak jauh, misalnya volume terlalu keras atau kurangnya kontrol."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Aktifkan stack fitur Gabeldorche Bluetooth."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Mengaktifkan stack fitur Gabeldorsche Bluetooth."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Terminal lokal"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Aktifkan aplikasi terminal yang menawarkan akses kerangka lokal"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Pemeriksaan HDCP"</string>
diff --git a/packages/SettingsLib/res/values-is/arrays.xml b/packages/SettingsLib/res/values-is/arrays.xml
index 1ac19f1..07b2ef1 100644
--- a/packages/SettingsLib/res/values-is/arrays.xml
+++ b/packages/SettingsLib/res/values-is/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (sjálfgefið)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Nota val kerfisins (sjálfgefið)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 8662615..438e900 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Virkja Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP-útgáfa"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Velja Bluetooth AVRCP-útgáfu"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetooth MAP-útgáfa"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Veldu Bluetooth MAP-útgáfu"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth hljóðkóðari"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Virkja Bluetooth-hljóðkóðara\nVal"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth hljóðtökutíðni"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Kanna skaðlega hegðun forrita sem sett eru upp frá ADB/ADT."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth-tæki án heita (aðeins MAC-vistfang) verða birt"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Slekkur á samstillingu Bluetooth-hljóðstyrks ef vandamál koma upp með hljóðstyrk hjá fjartengdum tækjum, svo sem of hár hljóðstyrkur eða erfiðleikar við stjórnun."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Virkjar Bluetooth Gabeldorche eiginleikastafla."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Kveikir á eiginleikastafla Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Staðbundin skipanalína"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Virkja skipanalínuforrit sem leyfir staðbundinn skeljaraðgang"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP-athugun"</string>
diff --git a/packages/SettingsLib/res/values-it/arrays.xml b/packages/SettingsLib/res/values-it/arrays.xml
index 44c519b..0bca8ea 100644
--- a/packages/SettingsLib/res/values-it/arrays.xml
+++ b/packages/SettingsLib/res/values-it/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (versione predefinita)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Usa selezione di sistema (predefinita)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 0e98d98..114b33b 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Attiva Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Versione Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Seleziona versione Bluetooth AVRCP"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Versione Bluetooth MAP"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Seleziona versione Bluetooth MAP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Codec audio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Attiva il codec audio Bluetooth\nSelezione"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Frequenza campionamento audio Bluetooth"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Controlla che le app installate tramite ADB/ADT non abbiano un comportamento dannoso"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Verranno mostrati solo dispositivi Bluetooth senza nome (solo indirizzo MAC)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Disattiva la funzione del volume assoluto Bluetooth in caso di problemi con il volume dei dispositivi remoti, ad esempio un volume troppo alto o la mancanza di controllo"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Consente di attivare lo stack delle funzionalità Bluetooth Gabeldorche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Consente di attivare lo stack delle funzionalità Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Terminale locale"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Abilita l\'app Terminale che offre l\'accesso alla shell locale"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Verifica HDCP"</string>
diff --git a/packages/SettingsLib/res/values-iw/arrays.xml b/packages/SettingsLib/res/values-iw/arrays.xml
index c8fc6d3..2f7f310 100644
--- a/packages/SettingsLib/res/values-iw/arrays.xml
+++ b/packages/SettingsLib/res/values-iw/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"‏MAP 1.2 (ברירת מחדל)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"שימוש בבחירת המערכת (ברירת המחדל)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 30a6295..62085a8 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"‏הפעלת Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"‏Bluetooth גרסה AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"‏בחר Bluetooth גרסה AVRCP"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"‏גרסת Bluetooth MAP"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"‏יש לבחור גרסה של Bluetooth MAP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"‏Codec אודיו ל-Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"‏הפעלת ‏Codec אודיו ל-Bluetooth\nבחירה"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"‏קצב דגימה של אודיו ל-Bluetooth"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"‏בדוק אפליקציות שהותקנו באמצעות ADB/ADT לאיתור התנהגות מזיקה."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"‏יוצגו מכשירי Bluetooth ללא שמות (כתובות MAC בלבד)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"‏משבית את תכונת עוצמת הקול המוחלטת ב-Bluetooth במקרה של בעיות בעוצמת הקול במכשירים מרוחקים, כגון עוצמת קול רמה מדי או חוסר שליטה ברמת העוצמה."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"‏הפעלת מקבץ הפיצ\'רים של Bluetooth Gabeldorche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"‏הפעלת מקבץ הפיצ\'רים של Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"מסוף מקומי"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"הפעל אפליקציית מסוף המציעה גישה מקומית למעטפת"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"‏בדיקת HDCP"</string>
diff --git a/packages/SettingsLib/res/values-ja/arrays.xml b/packages/SettingsLib/res/values-ja/arrays.xml
index fdc68c6..2966f09 100644
--- a/packages/SettingsLib/res/values-ja/arrays.xml
+++ b/packages/SettingsLib/res/values-ja/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2(デフォルト)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"システムの選択(デフォルト)を使用"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 22efe44..28b98ee 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche を有効にする"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP バージョン"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Bluetooth AVRCP バージョンを選択する"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetooth MAP バージョン"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Bluetooth MAP バージョンの選択"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth オーディオ コーデック"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth オーディオ コーデックを起動\n選択"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth オーディオ サンプルレート"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ADB/ADT経由でインストールされたアプリに不正な動作がないかを確認する"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth デバイスを名前なしで(MAC アドレスのみで)表示します"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"リモートデバイスで音量に関する問題(音量が大きすぎる、制御できないなど)が発生した場合に、Bluetooth の絶対音量の機能を無効にする"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Bluetooth Gabeldorche 機能スタックを有効にします。"</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Bluetooth Gabeldorsche 機能スタックを有効にします。"</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"ローカルターミナル"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"ローカルシェルアクセスを提供するターミナルアプリを有効にします"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCPチェック"</string>
diff --git a/packages/SettingsLib/res/values-ka/arrays.xml b/packages/SettingsLib/res/values-ka/arrays.xml
index dda3b07..5a86eae 100644
--- a/packages/SettingsLib/res/values-ka/arrays.xml
+++ b/packages/SettingsLib/res/values-ka/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (ნაგულისხმევი)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"სისტემის არჩეულის გამოყენება (ნაგულისხმევი)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 0139f58..6f5d0b3 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche-ის ჩართვა"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth-ის AVRCP-ის ვერსია"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"აირჩიეთ Bluetooth-ის AVRCP-ის ვერსია"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetooth MAP-ის ვერსია"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"აირჩიეთ Bluetooth MAP-ის ვერსია"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth აუდიოს კოდეკი"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth-ის აუდიო კოდეკის გაშვება\nარჩევანი"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth აუდიოს დისკრეტიზაციის სიხშირე"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"შეამოწმეთ, რამდენად უსაფრთხოა ADB/ADT-ის საშუალებით ინსტალირებული აპლიკაციები."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth-მოწყობილობები ნაჩვენები იქნება სახელების გარეშე (მხოლოდ MAC-მისამართები)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"გათიშავს Bluetooth-ის ხმის აბსოლუტური სიძლიერის ფუნქციას დისტანციურ მოწყობილობებზე ხმასთან დაკავშირებული ისეთი პრობლემების არსებობის შემთხვევაში, როგორიცაა ხმის დაუშვებლად მაღალი სიძლიერე ან კონტროლის შეუძლებლობა."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"ჩართავს Bluetooth Gabeldorche-ის ფუნქციების დასტას."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"ჩართავს Bluetooth Gabeldorsche-ის ფუნქციების დასტას."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"ადგილობრივი ტერმინალი"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"ლოკალურ გარსზე წვდომის ტერმინალური აპლიკაციის ჩართვა"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP შემოწმება"</string>
diff --git a/packages/SettingsLib/res/values-kk/arrays.xml b/packages/SettingsLib/res/values-kk/arrays.xml
index 70119c8..3c96f43 100644
--- a/packages/SettingsLib/res/values-kk/arrays.xml
+++ b/packages/SettingsLib/res/values-kk/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (әдепкі)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Жүйенің таңдағанын алу (әдепкі)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index f7a773a..3fe426e 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche функциясын іске қосу"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP нұсқасы"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Bluetooth AVRCP нұсқасын таңдау"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetooth MAP нұсқасы"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Bluetooth MAP нұсқасын таңдау"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth аудиокодегі"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth аудиокодегін іске қосу\nТаңдау"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth арқылы дыбыс іріктеу жиілігі"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ADB/ADT арқылы орнатылған қолданбалардың қауіпсіздігін тексеру."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth құрылғылары атаусыз (тек MAC мекенжайымен) көрсетіледі"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Қашықтағы құрылғыларда дыбыстың тым қатты шығуы немесе реттеуге келмеуі сияқты дыбыс деңгейіне қатысты мәселелер туындағанда, Bluetooth абсолютті дыбыс деңгейі функциясын өшіреді."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Bluetooth Gabeldorche функциясын іске қосады."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Bluetooth Gabeldorsche функциясы стегін қосады."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Жергілікті терминал"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Жергілікті шелл-код қол жетімділігін ұсынатын терминалды қолданбаны қосу"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP тексеру"</string>
diff --git a/packages/SettingsLib/res/values-km/arrays.xml b/packages/SettingsLib/res/values-km/arrays.xml
index 327754b..24efd08 100644
--- a/packages/SettingsLib/res/values-km/arrays.xml
+++ b/packages/SettingsLib/res/values-km/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (លំនាំដើម)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"ប្រើ​ការ​ជ្រើសរើស​ប្រព័ន្ធ (លំនាំ​ដើម)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 5c64a40..24bfa35 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"បើក Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"កំណែប្ល៊ូធូស AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"ជ្រើសរើសកំណែប្ល៊ូធូស AVRCP"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"កំណែ​ប៊្លូធូស MAP"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"ជ្រើសរើស​កំណែ​ប្ល៊ូធូស MAP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"កូឌិក​សំឡេង​ប៊្លូធូស"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ជំរុញ​ការជ្រើសរើស​កូឌិក​សំឡេង​\n​ប៊្លូធូស"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"អត្រា​គំរូ​សំឡេង​ប៊្លូធូស"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ពិនិត្យ​កម្មវិធី​បាន​ដំឡើង​តាម​រយៈ ADB/ADT សម្រាប់​ឥរិយាបថ​ដែល​គ្រោះ​ថ្នាក់។"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"​ឧបករណ៍​ប្ល៊ូធូសគ្មានឈ្មោះ​ (អាសយដ្ឋាន MAC តែប៉ុណ្ណោះ) នឹង​បង្ហាញ"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"បិទមុខងារកម្រិតសំឡេងឮខ្លាំងពេលភ្ជាប់ប៊្លូធូសក្នុងករណីមានបញ្ហាជាមួយឧបករណ៍បញ្ជាពីចម្ងាយ ដូចជាកម្រិតសំឡេងឮខ្លាំងដែលមិនអាចទទួលយកបាន ឬខ្វះការគ្រប់គ្រង។"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"បើក​ជង់​មុខងារ​ប៊្លូធូស Gabeldorche​។"</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"បើកជង់​មុខងារ​ប៊្លូធូស Gabeldorsche។"</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"ស្ថានីយ​មូលដ្ឋាន"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"បើក​កម្មវិធី​ស្ថានីយ​ដែល​ផ្ដល់​ការ​ចូល​សែល​មូលដ្ឋាន"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"ពិនិត្យ HDCP"</string>
diff --git a/packages/SettingsLib/res/values-kn/arrays.xml b/packages/SettingsLib/res/values-kn/arrays.xml
index b06af1c..4d8bde2 100644
--- a/packages/SettingsLib/res/values-kn/arrays.xml
+++ b/packages/SettingsLib/res/values-kn/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (ಡೀಫಾಲ್ಟ್)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 08a0db7..0699bbc 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"ಬ್ಲೂಟೂತ್ AVRCP ಆವೃತ್ತಿ"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"ಬ್ಲೂಟೂತ್ AVRCP ಆವೃತ್ತಿಯನ್ನು ಆಯ್ಕೆ ಮಾಡಿ"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"ಬ್ಲೂಟೂತ್ MAP ಆವೃತ್ತಿ"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"ಬ್ಲೂಟೂತ್ MAP ಆವೃತ್ತಿಯನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"ಬ್ಲೂಟೂತ್ ಆಡಿಯೋ ಕೋಡೆಕ್"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ಬ್ಲೂಟೂತ್ ಆಡಿಯೋ ಕೋಡೆಕ್ ಅನ್ನು ಟ್ರಿಗ್ಗರ್ ಮಾಡಿ\nಆಯ್ಕೆ"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ಬ್ಲೂಟೂತ್ ಆಡಿಯೋ ಮಾದರಿ ದರ"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ಹಾನಿಮಾಡುವಂತಹ ವರ್ತನೆಗಾಗಿ ADB/ADT ಮೂಲಕ ಸ್ಥಾಪಿಸಲಾದ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"ಹೆಸರುಗಳಿಲ್ಲದ (ಕೇವಲ MAC ವಿಳಾಸಗಳು ಮಾತ್ರ) ಬ್ಲೂಟೂತ್ ಸಾಧನಗಳನ್ನು ಪ್ರದರ್ಶಿಸಲಾಗುತ್ತದೆ"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"ರಿಮೋಟ್ ಸಾಧನಗಳಲ್ಲಿ ಕಂಡುಬರುವ ಸ್ವೀಕಾರಾರ್ಹವಲ್ಲದ ಜೋರಾದ ವಾಲ್ಯೂಮ್ ಅಥವಾ ನಿಯಂತ್ರಣದ ಕೊರತೆಯಂತಹ ವಾಲ್ಯೂಮ್ ಸಮಸ್ಯೆಗಳಂತಹ ಸಂದರ್ಭದಲ್ಲಿ ಬ್ಲೂಟೂತ್‍ನ ನಿಚ್ಚಳ ವಾಲ್ಯೂಮ್ ವೈಶಿಷ್ಟ್ಯವನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"ಬ್ಲೂಟೂತ್ Gabeldorche ವೈಶಿಷ್ಟ್ಯದ ಸ್ಟ್ಯಾಕ್‌ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"ಬ್ಲೂಟೂತ್ Gabeldorsche ವೈಶಿಷ್ಟ್ಯದ ಸ್ಟ್ಯಾಕ್‌ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"ಸ್ಥಳೀಯ ಟರ್ಮಿನಲ್"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"ಸ್ಥಳೀಯ ಶೆಲ್ ಪ್ರವೇಶವನ್ನು ಒದಗಿಸುವ ಟರ್ಮಿನಲ್ ಅಪ್ಲಿಕೇಶನ್ ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP ಪರೀಕ್ಷಿಸುವಿಕೆ"</string>
diff --git a/packages/SettingsLib/res/values-ko/arrays.xml b/packages/SettingsLib/res/values-ko/arrays.xml
index 9f7a751..999f3ae 100644
--- a/packages/SettingsLib/res/values-ko/arrays.xml
+++ b/packages/SettingsLib/res/values-ko/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2(기본)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"시스템 설정 사용(기본)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index d93b1cd..25e9cfe 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche 사용 설정"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"블루투스 AVRCP 버전"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"블루투스 AVRCP 버전 선택"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"블루투스 MAP 버전"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"블루투스 MAP 버전 선택"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"블루투스 오디오 코덱"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"블루투스 오디오 코덱 실행\n선택"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"블루투스 오디오 샘플링 비율"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ADB/ADT를 통해 설치된 앱에 유해한 동작이 있는지 확인"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"이름이 없이 MAC 주소만 있는 블루투스 기기 표시"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"참기 어려울 정도로 볼륨이 크거나 제어가 되지 않는 등 원격 기기에서 볼륨 문제가 발생할 경우 블루투스 절대 볼륨 기능을 사용 중지"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"블루투스 Gabeldorche 기능 스택을 사용 설정합니다."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"블루투스 Gabeldorsche 기능 스택을 사용 설정합니다."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"로컬 터미널"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"로컬 셸 액세스를 제공하는 터미널 앱 사용"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP 확인"</string>
diff --git a/packages/SettingsLib/res/values-ky/arrays.xml b/packages/SettingsLib/res/values-ky/arrays.xml
index b2eaf9f..fd47dad 100644
--- a/packages/SettingsLib/res/values-ky/arrays.xml
+++ b/packages/SettingsLib/res/values-ky/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"КАРТА 1.2 (Демейки)"</item>
+    <item msgid="6817922176194686449">"КАРТА 1.3"</item>
+    <item msgid="3423518690032737851">"КАРТА 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"карта12"</item>
+    <item msgid="7073042887003102964">"карта13"</item>
+    <item msgid="8147982633566548515">"карта14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Тутум тандаганды колдонуу (демейки)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index a24dd65..3dfce1e 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche функциясын иштетүү"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP версиясы"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Bluetooth AVRCP версиясын тандоо"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetooth MAP версиясы"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Bluetooth MAP версиясын тандоо"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth аудио кодек"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth Audio кодегин иштетүү\nТандоо"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth аудио үлгүсүнүн ылдамдыгы"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ADB/ADT аркылуу орнотулган колдонмолордун коопсуздугу текшерилет."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Аталышсыз Bluetooth түзмөктөрү (MAC даректери менен гана) көрсөтүлөт"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Алыскы түзмөктөр өтө катуу добуш чыгарып же көзөмөлдөнбөй жатса Bluetooth \"Үндүн абсолюттук деңгээли\" функциясын өчүрөт."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Bluetooth Gabeldorche функциясынын топтомун иштетет."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Bluetooth Gabeldorsche функциясынын топтомун иштетет."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Жергиликтүү терминал"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Жергиликтүү буйрук кабыгын сунуштаган терминалга уруксат берүү"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP текшерүү"</string>
diff --git a/packages/SettingsLib/res/values-lo/arrays.xml b/packages/SettingsLib/res/values-lo/arrays.xml
index 7e7ea1f..5e25ab0 100644
--- a/packages/SettingsLib/res/values-lo/arrays.xml
+++ b/packages/SettingsLib/res/values-lo/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (Default)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"ໃຊ້ການເລືອກຂອງລະບົບ (ຄ່າເລີ່ມຕົ້ນ)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 3f93483..48e5093 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"ເປີດໃຊ້ Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"ເວີຊັນ Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"ເລືອກເວີຊັນ Bluetooth AVRCP"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"ເວີຊັນ Bluetooth MAP"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"ເລືອກເວີຊັນ Bluetooth MAP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth Audio Codec"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ເປີດໃຊ້ Bluetooth Audio Codec\nການເລືອກ"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth Audio Sample Rate"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ກວດສອບແອັບທີ່ຕິດຕັ້ງແລ້ວຜ່ານທາງ ADB/ADT ເພື່ອກວດຫາພຶດຕິກຳທີ່ເປັນອັນຕະລາຍ."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"ຈະສະແດງອຸປະກອນ Bluetooth ທີ່ບໍ່ມີຊື່ (ທີ່ຢູ່ MAC ເທົ່ານັ້ນ)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"ປິດໃຊ້ຄຸນສົມບັດລະດັບສຽງສົມບູນຂອງ Bluetooth ໃນກໍລະນີເກີດບັນຫາລະດັບສຽງສົມບູນກັບອຸປະກອນທາງໄກ ເຊັ່ນວ່າ ລະດັບສຽງດັງເກີນຍອມຮັບໄດ້ ຫຼື ຄວບຄຸມບໍ່ໄດ້."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"ເປີດໃຊ້ການວາງຊ້ອນຄຸນສົມບັດ Bluetooth Gabeldorche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"ເປີດໃຊ້ສະແຕັກຄຸນສົມບັດ Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Terminal ໃນໂຕເຄື່ອງ"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"ເປີດນຳໃຊ້ແອັບຯ Terminal ທີ່ໃຫ້ການເຂົ້າເຖິງ shell ໃນໂຕເຄື່ອງໄດ້"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"ການກວດສອບ HDCP"</string>
diff --git a/packages/SettingsLib/res/values-lt/arrays.xml b/packages/SettingsLib/res/values-lt/arrays.xml
index 3356efb..e4b55ab 100644
--- a/packages/SettingsLib/res/values-lt/arrays.xml
+++ b/packages/SettingsLib/res/values-lt/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"1.2 versijos MRK (numatytoji)"</item>
+    <item msgid="6817922176194686449">"1.3 versijos MRK"</item>
+    <item msgid="3423518690032737851">"1.4 versijos MRK"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Naudoti sistemos pasirink. (numatytasis)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 9409093..8b3fbad 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Įgalinti „Gabeldorsche“"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"„Bluetooth“ AVRCP versija"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Pasirinkite „Bluetooth“ AVRCP versiją"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"„Bluetooth“ MRK versija"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Pasirinkite „Bluetooth“ MRK versiją"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"„Bluetooth“ garso kodekas"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Suaktyvinti „Bluetooth“ garso kodeką\nPasirinkimas"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"„Bluetooth“ garso pavyzdžio dažnis"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Patikrinkite, ar programų, įdiegtų naudojant ADB / ADT, veikimas nėra žalingas."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bus rodomi „Bluetooth“ įrenginiai be pavadinimų (tik MAC adresai)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Išjungiama „Bluetooth“ didžiausio garso funkcija, jei naudojant nuotolinio valdymo įrenginius kyla problemų dėl garso, pvz., garsas yra per didelis arba jo negalima tinkamai valdyti."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Įgalinama „Bluetooth Gabeldorche“ funkcijų grupė."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Įgalinama „Bluetooth Gabeldorsche“ funkcijų grupė."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Vietinis terminalas"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Įgal. terminalo progr., siūlančią prieigą prie viet. apvalkalo"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP tikrinimas"</string>
diff --git a/packages/SettingsLib/res/values-lv/arrays.xml b/packages/SettingsLib/res/values-lv/arrays.xml
index 2f0f507..b90cf22 100644
--- a/packages/SettingsLib/res/values-lv/arrays.xml
+++ b/packages/SettingsLib/res/values-lv/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (noklusējums)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Sistēmas atlases izmantošana (nokl.)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index b51b69a..4fc5b22 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Iespējot Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP versija"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Atlasiet Bluetooth AVRCP versiju"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetooth MAP versija"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Atlasiet Bluetooth MAP versiju"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth audio kodeks"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Aktivizēt Bluetooth audio kodeku\nAtlase"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth audio iztveršanas ātrums"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Pārbaudīt, vai lietotņu, kuru instalēšanai izmantots ADB/ADT, darbība nav kaitīga."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Tiks parādītas Bluetooth ierīces bez nosaukumiem (tikai MAC adreses)."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Atspējo Bluetooth absolūtā skaļuma funkciju skaļuma problēmu gadījumiem attālajās ierīcēs, piemēram, ja ir nepieņemami liels skaļums vai nav iespējas kontrolēt skaļumu."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Šis iestatījums iespējo funkciju grupu Bluetooth Gabeldorche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Tiek iespējota funkciju grupa Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Vietējā beigu lietotne"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Iespējot beigu lietotni, kurā piedāvāta vietējā čaulas piekļuve"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP pārbaude"</string>
diff --git a/packages/SettingsLib/res/values-mk/arrays.xml b/packages/SettingsLib/res/values-mk/arrays.xml
index 3753a51..90956ad 100644
--- a/packages/SettingsLib/res/values-mk/arrays.xml
+++ b/packages/SettingsLib/res/values-mk/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (стандардна)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Користи избор на системот (стандардно)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index d38301e..288e526 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Овозможи Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Верзија Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Изберете верзија Bluetooth AVRCP"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Верзија на Bluetooth MAP"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Изберете верзија на Bluetooth MAP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Кодек за аудио преку Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Вклучете го аудио кодекот преку Bluetooth\nСелекција"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Стапка на семпл преку Bluetooth"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Провери апликации инсталирани преку ADB/ADT за штетно однесување."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Уредите со Bluetooth без имиња (само MAC-адреси) ќе се прикажуваат"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Ја оневозможува карактеристиката за апсолутна јачина на звук преку Bluetooth во случај кога ќе настанат проблеми со далечинските уреди, како на пр., неприфатливо силен звук или недоволна контрола."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Ја овозможува функцијата Bluetooth Gabeldorche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Ја овозможува функцијата Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Локален терминал"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Овозможи апликација на терминал што овозможува локален пристап кон школка."</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Проверување HDCP"</string>
diff --git a/packages/SettingsLib/res/values-ml/arrays.xml b/packages/SettingsLib/res/values-ml/arrays.xml
index 1e07994..60eb24e 100644
--- a/packages/SettingsLib/res/values-ml/arrays.xml
+++ b/packages/SettingsLib/res/values-ml/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (ഡിഫോൾട്ട്)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ ‌(ഡിഫോൾട്ട്)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 27019d1..e775297 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche പ്രവർത്തനക്ഷമമാക്കുക"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP പതിപ്പ്"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Bluetooth AVRCP പതിപ്പ് തിരഞ്ഞെടുക്കുക"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetooth MAP പതിപ്പ്"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Bluetooth MAP പതിപ്പ് തിരഞ്ഞെടുക്കുക"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth ഓഡിയോ കോഡെക്"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth Audio Codec\nSelection ട്രിഗ്ഗര്‍ ചെയ്യുക"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth ഓഡിയോ സാമ്പിൾ നിരക്ക്"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ADB/ADT വഴി ഇൻസ്റ്റാൾ ചെയ്‌ത കേടാക്കുന്ന പ്രവർത്തനരീതിയുള്ള ആപ്പുകൾ പരിശോധിക്കുക."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"പേരില്ലാത്ത Bluetooth ഉപകരണങ്ങൾ (MAC വിലാസങ്ങൾ മാത്രം) പ്രദർശിപ്പിക്കും"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"അസ്വീകാര്യമായ തരത്തിൽ ഉയർന്ന വോളിയമോ ശബ്ദ നിയന്ത്രണത്തിന്റെ അഭാവമോ പോലെ, വിദൂര ഉപകരണങ്ങളുമായി ബന്ധപ്പെട്ട വോളിയം പ്രശ്നങ്ങൾ ഉണ്ടാകുന്ന സാഹചര്യത്തിൽ, Bluetooth അബ്‌സൊല്യൂട്ട് വോളിയം ഫീച്ചർ പ്രവർത്തനരഹിതമാക്കുന്നു."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Bluetooth Gabeldorche ഫീച്ചർ സ്‌റ്റാക്ക് പ്രവർത്തനക്ഷമമാക്കുന്നു."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Bluetooth Gabeldorsche ഫീച്ചർ സ്റ്റാക്ക് പ്രവർത്തനക്ഷമമാക്കുന്നു."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"പ്രാദേശിക ടെർമിനൽ"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"പ്രാദേശിക ഷെൽ ആക്‌സസ് നൽകുന്ന ടെർമിനൽ അപ്ലിക്കേഷൻ പ്രവർത്തനക്ഷമമാക്കുക"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP പരിശോധന"</string>
diff --git a/packages/SettingsLib/res/values-mn/arrays.xml b/packages/SettingsLib/res/values-mn/arrays.xml
index d1eca7b..ce868af 100644
--- a/packages/SettingsLib/res/values-mn/arrays.xml
+++ b/packages/SettingsLib/res/values-mn/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (өгөгдмөл)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Системийн сонголтыг ашиглах (Өгөгдмөл)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index f0136c9..ba69f9b 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche-г идэвхжүүлэх"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP хувилбар"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Bluetooth AVRCP хувилбарыг сонгох"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetooth MAP хувилбар"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Bluetooth MAP хувилбарыг сонгох"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth аудио кодлогч"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth-н аудио кодлогчийг өдөөх\nСонголт"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth аудио жишээний үнэлгээ"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ADB/ADT-р суулгасан апп-уудыг хорлонтой авиртай эсэхийг шалгах."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Нэргүй Bluetooth төхөөрөмжийг (зөвхөн MAC хаяг) харуулна"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Хэт чанга дуугаралт эсвэл муу тохиргоо зэрэг алсын зайн төхөөрөмжийн дуугаралттай холбоотой асуудлын үед Bluetooth-ийн үнэмлэхүй дууны түвшинг идэвхгүй болго."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Bluetooth Gabeldorsche онцлогийн өрөлтийг идэвхжүүлдэг."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Bluetooth Gabeldorsche онцлогийн өрөлтийг идэвхжүүлдэг."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Локал терминал"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Локал суурьт хандалт хийх боломж олгодог терминалын апп-г идэвхжүүлэх"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP шалгах"</string>
diff --git a/packages/SettingsLib/res/values-mr/arrays.xml b/packages/SettingsLib/res/values-mr/arrays.xml
index e62e6ff..3e6e3d0 100644
--- a/packages/SettingsLib/res/values-mr/arrays.xml
+++ b/packages/SettingsLib/res/values-mr/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (डीफॉल्ट)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"सिस्टम निवड वापरा (डीफॉल्ट)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 4d8069e..1930cdf 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"गाबलडॉर्ष सुरू करा"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"ब्लूटूथ AVRCP आवृत्ती"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"ब्लूटूथ AVRCP आवृत्ती निवडा"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"ब्लूटूथ MAP आवृत्ती"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"ब्लूटूथ MAP आवृत्ती निवडा"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"ब्लूटूथ ऑडिओ कोडेक"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ब्लूटूथ ऑडिओ Codec ट्रिगर करा\nनिवड"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ब्लूटूथ ऑडिओ पॅटर्न दर"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"हानिकारक वर्तनासाठी ADB/ADT द्वारे इंस्टॉल अ‍ॅप्स तपासा."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"नावांशिवाय ब्‍लूटूथ डीव्‍हाइस (फक्‍त MAC पत्‍ते) दाखवले जातील"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"रिमोट डिव्हाइसमध्ये सहन न होणारा मोठा आवाज किंवा नियंत्रणाचा अभाव यासारखी आवाजाची समस्या असल्यास ब्लूटूथ संपूर्ण आवाज वैशिष्ट्य बंद करते."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"ब्लूटूथ गाबलडॉर्ष वैशिष्ट्य स्टॅक सुरू करते."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"ब्लूटूथ गाबलडॉर्ष वैशिष्‍ट्य स्टॅक सुरू करा."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"स्थानिक टर्मिनल"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"स्थानिक शेल प्रवेश देणारा टर्मिनल अ‍ॅप सुरू करा"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP तपासणी"</string>
diff --git a/packages/SettingsLib/res/values-ms/arrays.xml b/packages/SettingsLib/res/values-ms/arrays.xml
index 91dd81c..a2d314b 100644
--- a/packages/SettingsLib/res/values-ms/arrays.xml
+++ b/packages/SettingsLib/res/values-ms/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (Lalai)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Gunakan Pilihan Sistem (Lalai)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 7efc9875..e493188 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Dayakan Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Versi AVRCP Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Pilih Versi AVRCP Bluetooth"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Versi MAP Bluetooth"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Pilih Versi MAP Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Codec Audio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Cetuskan Codec Audio Bluetooth\nPilihan"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Kadar Sampel Audio Bluetooth"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Semak apl yang dipasang melalui ADB/ADT untuk tingkah laku yang berbahaya."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Peranti Bluetooth tanpa nama (alamat MAC sahaja) akan dipaparkan"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Lumpuhkan ciri kelantangan mutlak Bluetooth dalam kes isu kelantangan menggunakan peranti kawalan jauh seperti kelantangan yang sangat kuat atau tidak dapat mengawal."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Mendayakan tindanan ciri Bluetooth Gabeldorche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Mendayakan tindanan ciri Gabeldorche Bluetooth."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Terminal setempat"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Dayakan apl terminal yang menawarkan akses shell tempatan"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Penyemakan HDCP"</string>
diff --git a/packages/SettingsLib/res/values-my/arrays.xml b/packages/SettingsLib/res/values-my/arrays.xml
index 9c4a2b9..dbeabc0 100644
--- a/packages/SettingsLib/res/values-my/arrays.xml
+++ b/packages/SettingsLib/res/values-my/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (မူရင်း)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"စနစ်ရွေးချယ်မှုကို အသုံးပြုပါ (မူရင်း)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index befdaa9..2c4b32c 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche ကို ဖွင့်ရန်"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"ဘလူးတုသ် AVRCP ဗားရှင်း"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"ဘလူးတုသ် AVRCP ဗားရှင်းကို ရွေးပါ"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"ဘလူးတုသ် MAP ဗားရှင်း"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"ဘလူးတုသ် MAP ဗားရှင်းကို ရွေးပါ"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"ဘလူးတုသ်အသံ ကိုးဒက်ခ်"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ဘလူးတုသ် အသံ LDAC ကိုးဒက်ခ် ဖွင့်ခြင်း\nရွေးချယ်မှု"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ဘလူးတုသ်အသံနမူနာနှုန်း"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ADB/ADT မှတစ်ဆင့် ထည့်သွင်းသော အက်ပ်များ အန္တရာယ်ဖြစ်နိုင်ခြင်း ရှိမရှိ စစ်ဆေးသည်။"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"အမည်မရှိသော (MAC လိပ်စာများသာပါသော) ဘလူးတုသ်စက်ပစ္စည်းများကို ပြသပါမည်"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"ချိတ်ဆက်ထားသည့် ကိရိယာတွင် လက်မခံနိုင်လောက်အောင် ဆူညံ သို့မဟုတ် ထိန်းညှိမရနိုင်သော အသံပိုင်းပြဿနာ ရှိခဲ့လျှင် ဘလူးတုသ် ပကတိ အသံနှုန်းကို ပိတ်ပါ။"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"ဘလူးတုသ် Gabeldorche အထူးတည်းဖြတ်ခြင်းကို ဖွင့်သည်။"</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"ဘလူးတုသ် Gabeldorsche လုပ်ဆောင်ချက်အပိုင်းကို ဖွင့်သည်။"</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"လိုကယ်တာမီနယ်"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"local shell အသုံးပြုခွင့်ကမ်းလှမ်းသော တာမင်နယ်အပလီကေးရှင်းဖွင့်ပါ"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP စစ်ဆေးမှု"</string>
diff --git a/packages/SettingsLib/res/values-nb/arrays.xml b/packages/SettingsLib/res/values-nb/arrays.xml
index ed045ad..8d005b3 100644
--- a/packages/SettingsLib/res/values-nb/arrays.xml
+++ b/packages/SettingsLib/res/values-nb/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (standard)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Bruk systemvalg (standard)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index cb0931f..093c06f 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Aktiver Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP-versjon"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Velg Bluetooth AVRCP-versjon"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetooth MAP-versjon"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Velg Bluetooth MAP-versjon"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Kodek for Bluetooth-lyd"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Utløs kodek for Bluetooth-lyd\nValg"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Samplefrekvens for Bluetooth-lyd"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Sjekk apper som er installert via ADB/ADT, for skadelig atferd."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth-enheter uten navn (bare MAC-adresser) vises"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Slår av funksjonen for absolutt volum via Bluetooth i tilfelle det oppstår volumrelaterte problemer med eksterne enheter, for eksempel uakseptabelt høyt volum eller mangel på kontroll."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Aktiverer funksjonsstabelen Bluetooth Gabeldorche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Aktiverer funksjonsstabelen Bluetooth Gabeldorsche"</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Lokal terminal"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Aktiver terminalappen som gir lokal kommandolistetilgang"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP-kontroll"</string>
diff --git a/packages/SettingsLib/res/values-ne/arrays.xml b/packages/SettingsLib/res/values-ne/arrays.xml
index c8ee48b..5d79e80 100644
--- a/packages/SettingsLib/res/values-ne/arrays.xml
+++ b/packages/SettingsLib/res/values-ne/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp १५"</item>
     <item msgid="1963366694959681026">"avrcp १६"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP १.२ (पूर्वनिर्धारित)"</item>
+    <item msgid="6817922176194686449">"MAP १.३"</item>
+    <item msgid="3423518690032737851">"MAP १.४"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"प्रणालीको चयन प्रयोग गर्नुहोस् (पूर्वनिर्धारित)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index c7ffc64..fb8b737 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche सक्षम पार्नुहोस्"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"ब्लुटुथको AVRCP संस्करण"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"ब्लुटुथको AVRCP संस्करण चयन गर्नुहोस्"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"ब्लुटुथको MAP संस्करण"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"ब्लुटुथको MAP संस्करण चयन गर्नुहोस्"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"ब्लुटुथ अडियोको कोडेक"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ब्लुटुथ अडियो कोडेक ट्रिगर गर्नुहोस्\nचयन"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ब्लुटुथ अडियोको नमूना दर"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"हानिकारक व्यवहारको लागि ADB/ADT को माध्यमबाट स्थापित अनुप्रयोगहरूको जाँच गर्नुहोस्।"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"नामकरण नगरिएका ब्लुटुथ यन्त्रहरू (MAC ठेगाना भएका मात्र) देखाइनेछ"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"रिमोट यन्त्रहरूमा अस्वीकार्य चर्को आवाज वा नियन्त्रणमा कमी जस्ता आवाज सम्बन्धी समस्याहरूको अवस्थामा ब्लुटुथ निरपेक्ष आवाज सुविधालाई असक्षम गराउँछ।"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"ब्लुटुथ Gabeldorche सुविधाको स्ट्याक सक्षम पार्नुहोस्।"</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"ब्लुटुथ Gabeldorsche सुविधाको स्ट्याक सक्षम पार्नुहोस्।"</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"स्थानीय टर्मिनल"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"स्थानीय सेल पहुँच प्रदान गर्ने टर्मिनल अनुप्रयोग सक्षम गर्नुहोस्"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP जाँच गर्दै"</string>
diff --git a/packages/SettingsLib/res/values-nl/arrays.xml b/packages/SettingsLib/res/values-nl/arrays.xml
index d86dab6..9b94ae50 100644
--- a/packages/SettingsLib/res/values-nl/arrays.xml
+++ b/packages/SettingsLib/res/values-nl/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (standaard)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Systeemselectie gebruiken (standaard)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index a196ccf..267dab4 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche inschakelen"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth-AVRCP-versie"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Bluetooth-AVRCP-versie selecteren"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"MAP-versie voor bluetooth"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"MAP-versie voor bluetooth selecteren"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth-audiocodec"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Codec voor Bluetooth-audio activeren\nSelectie"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Sample rate van Bluetooth-audio"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Apps die zijn geïnstalleerd via ADB/ADT, controleren op schadelijk gedrag"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth-apparaten zonder namen (alleen MAC-adressen) worden weergegeven"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Hiermee wordt de functie voor absoluut volume van Bluetooth uitgeschakeld in geval van volumeproblemen met externe apparaten, zoals een onacceptabel hoog volume of geen volumeregeling."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Hierdoor wordt de Gabeldorsche-functiestack voor bluetooth ingeschakeld"</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Hierdoor wordt de Gabeldorsche-functiestack voor bluetooth ingeschakeld."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Lokale terminal"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Terminal-app inschakelen die lokale shell-toegang biedt"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP-controle"</string>
diff --git a/packages/SettingsLib/res/values-or/arrays.xml b/packages/SettingsLib/res/values-or/arrays.xml
index 2553978..a021446 100644
--- a/packages/SettingsLib/res/values-or/arrays.xml
+++ b/packages/SettingsLib/res/values-or/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (ଡିଫଲ୍ଟ)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"ସିଷ୍ଟମ୍ ଚୟନ ବ୍ୟବହାର କରନ୍ତୁ (ଡିଫଲ୍ଟ)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index faa399d..d8ae3bf 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"ଗାବେଲ୍‌ଡୋର୍ସ ସକ୍ରିୟ କରନ୍ତୁ"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"ବ୍ଲୁଟୂଥ୍‌ AVRCP ଭର୍ସନ୍"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"ବ୍ଲୁଟୂଥ୍‍‌ AVRCP ଭର୍ସନ୍‌"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"ବ୍ଲୁଟୁଥ୍ MAP ସଂସ୍କରଣ"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"ବ୍ଲୁଟୁଥ୍ MAP ସଂସ୍କରଣ ଚୟନ କରନ୍ତୁ"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"ବ୍ଲୁଟୁଥ୍‌ ଅଡିଓ କୋଡେକ୍‌"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ବ୍ଲୁଟୂଥ୍‍ ଅଡିଓ କୋଡେକ୍\nସିଲେକ୍ସନ୍‌କୁ ଗତିଶୀଳ କରନ୍ତୁ"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ବ୍ଲୁଟୂଥ୍‌ ଅଡିଓ ସାମ୍ପଲ୍‌ ରେଟ୍‌"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ADB/ADT ମାଧ୍ୟମରେ ଇନଷ୍ଟଲ ହୋଇଥିବା ଆପ୍‌ଗୁଡ଼ିକ କ୍ଷତିକାରକ କି ନୁହେଁ ଯାଞ୍ଚ କରନ୍ତୁ।"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"(କେବଳ MAC ଠିକଣା ଥାଇ) ନାମ ବିନା ବ୍ଲୁଟୂଥ ଡିଭାଇସଗୁଡ଼ିକ ପ୍ରଦର୍ଶିତ ହେବ"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"ରିମୋଟ୍‌ ଡିଭାଇସ୍‌ଗୁଡ଼ିକରେ ଯଦି ଅସ୍ୱୀକାର୍ଯ୍ୟ ଭାବେ ଉଚ୍ଚ ଭଲ୍ୟୁମ୍ କିମ୍ବା ନିୟନ୍ତ୍ରଣର ଅଭାବ ପରି ଭଲ୍ୟୁମ୍ ସମସ୍ୟା ଥାଏ, ବ୍ଲୁଟୂଥ୍‌ ପୂର୍ଣ୍ଣ ଭଲ୍ୟୁମ୍ ଫିଚର୍ ଅକ୍ଷମ କରିଥାଏ।"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"ବ୍ଲୁଟୁଥ୍ ଗାବେଲ୍‌ଡୋର୍ସ ଫିଚର୍ ଷ୍ଟକ୍ ସକ୍ଷମ କରେ।"</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"ବ୍ଲୁଟୁଥ୍ ଗାବେଲଡୋର୍ସ ଫିଚର୍ ଷ୍ଟକ୍ ସକ୍ଷମ କରେ।"</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"ସ୍ଥାନୀୟ ଟର୍ମିନାଲ୍‌"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"ସ୍ଥାନୀୟ ଶେଲ୍‌କୁ ଆକ‌ସେସ୍‌ ଦେଉଥିବା ଟର୍ମିନଲ୍‌ ଆପ୍‌କୁ ସକ୍ଷମ କରନ୍ତୁ"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP ଯାଞ୍ଚ କରୁଛି"</string>
diff --git a/packages/SettingsLib/res/values-pa/arrays.xml b/packages/SettingsLib/res/values-pa/arrays.xml
index 8acc439..48e7fb4 100644
--- a/packages/SettingsLib/res/values-pa/arrays.xml
+++ b/packages/SettingsLib/res/values-pa/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"ਸਿਸਟਮ ਚੋਣ ਦੀ ਵਰਤੋਂ ਕਰੋ (ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index cd83c2c..6a78486 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche ਨੂੰ ਚਾਲੂ ਕਰੋ"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"ਬਲੂਟੁੱਥ AVRCP ਵਰਜਨ"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"ਬਲੂਟੁੱਥ AVRCP ਵਰਜਨ ਚੁਣੋ"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetooth MAP ਵਰਜਨ"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Bluetooth MAP ਵਰਜਨ ਚੁਣੋ"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"ਬਲੂਟੁੱਥ ਆਡੀਓ ਕੋਡੇਕ"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ਬਲੂਟੁੱਥ ਆਡੀਓ ਕੋਡੇਕ\nਚੋਣ ਨੂੰ ਟ੍ਰਿਗਰ ਕਰੋ"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ਬਲੂਟੁੱਥ ਆਡੀਓ ਸੈਂਪਲ ਰੇਟ"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ਹਾਨੀਕਾਰਕ ਵਿਵਹਾਰ ਲਈ ADB/ADT ਰਾਹੀਂ ਸਥਾਪਤ ਕੀਤੀਆਂ ਐਪਾਂ ਦੀ ਜਾਂਚ ਕਰੋ।"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"ਅਨਾਮ ਬਲੂਟੁੱਥ ਡੀਵਾਈਸਾਂ ਦਿਖਾਈਆਂ ਜਾਣਗੀਆਂ (ਸਿਰਫ਼ MAC ਪਤੇ)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"ਰਿਮੋਟ ਡੀਵਾਈਸਾਂ ਨਾਲ ਅਵਾਜ਼ੀ ਸਮੱਸਿਆਵਾਂ ਜਿਵੇਂ ਕਿ ਨਾ ਪਸੰਦ ਕੀਤੀ ਜਾਣ ਵਾਲੀ ਉੱਚੀ ਅਵਾਜ਼ ਜਾਂ ਕੰਟਰੋਲ ਦੀ ਕਮੀ ਵਰਗੀ ਹਾਲਤ ਵਿੱਚ ਬਲੂਟੁੱਥ ਪੂਰਨ ਅਵਾਜ਼ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਬੰਦ ਕਰਦਾ ਹੈ।"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"ਬਲੂਟੁੱਥ Gabeldorche ਵਿਸ਼ੇਸ਼ਤਾ ਸਟੈਕ ਨੂੰ ਚਾਲੂ ਕਰਦਾ ਹੈ।"</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"ਬਲੂਟੁੱਥ Gabeldorsche ਵਿਸ਼ੇਸ਼ਤਾ ਸਟੈਕ ਨੂੰ ਚਾਲੂ ਕਰਦਾ ਹੈ।"</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"ਸਥਾਨਕ ਟਰਮੀਨਲ"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"ਟਰਮੀਨਲ ਐਪ ਨੂੰ ਚਾਲੂ ਕਰੋ ਜੋ ਸਥਾਨਕ ਸ਼ੈਲ ਪਹੁੰਚ ਪੇਸ਼ਕਸ਼ ਕਰਦਾ ਹੈ"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP ਜਾਂਚ"</string>
diff --git a/packages/SettingsLib/res/values-pl/arrays.xml b/packages/SettingsLib/res/values-pl/arrays.xml
index 00b23bc..43b8f5f 100644
--- a/packages/SettingsLib/res/values-pl/arrays.xml
+++ b/packages/SettingsLib/res/values-pl/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (domyślny)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Użyj wyboru systemu (domyślnie)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index b47365b..8c5547c 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Włącz Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Wersja AVRCP Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Wybierz wersję AVRCP Bluetooth"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Wersja MAP Bluetooth"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Wybierz wersję MAP Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Kodek dźwięku Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Uruchom kodek dźwięku Bluetooth\nWybór"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Dźwięk Bluetooth – współczynnik próbkowania"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Sprawdź, czy aplikacje zainstalowane przez ADB/ADT nie zachowują się w szkodliwy sposób"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Zostaną wyświetlone urządzenia Bluetooth bez nazw (tylko adresy MAC)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Wyłącza funkcję Głośność bezwzględna Bluetooth, jeśli występują problemy z urządzeniami zdalnymi, np. zbyt duża głośność lub brak kontroli."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Włącza funkcje Bluetooth Gabeldorche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Włącza funkcje Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Terminal lokalny"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Włącz terminal, który umożliwia dostęp do powłoki lokalnej"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Sprawdzanie HDCP"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/arrays.xml b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
index 4e23c19..4658ffd 100644
--- a/packages/SettingsLib/res/values-pt-rBR/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (padrão)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Usar seleção do sistema (padrão)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 4cccad4..8c03616 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Ativar Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Versão do Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Selecionar versão do Bluetooth AVRCP"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Versão MAP do Bluetooth"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Selecionar versão MAP do Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Codec de áudio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Acionar codec de áudio Bluetooth\nSeleção"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Taxa de amostra do áudio Bluetooth"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Verificar comportamento nocivo em apps instalados via ADB/ADT"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Dispositivos Bluetooth sem nomes (somente endereços MAC) serão exibidos"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Desativa o recurso Bluetooth de volume absoluto em caso de problemas com o volume em dispositivos remotos, como volume excessivamente alto ou falta de controle"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Ativa a pilha de recursos Bluetooth Gabeldorsche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Ativa a pilha de recursos Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Terminal local"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Ativar o app terminal que oferece acesso ao shell local"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Verificação HDCP"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/arrays.xml b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
index 98e9c87..527f740 100644
--- a/packages/SettingsLib/res/values-pt-rPT/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (predefinição)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Utilizar seleção do sistema (predefinido)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 6e80bd2..6aeff1c 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Ativar o Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Versão de Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Selecionar versão de Bluetooth AVRCP"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Versão do MAP do Bluetooth"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Selecione a versão do MAP do Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Codec de áudio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Acionar o codec de áudio Bluetooth\nSeleção"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Taxa de amostragem de áudio Bluetooth"</string>
@@ -241,7 +243,7 @@
     <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="2076949781460359589">"Acionar o codec de áudio Bluetooth\nSeleção: modo de canal"</string>
     <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3233402355917446304">"Codec LDAC de áudio Bluetooth: qualidade de reprodução"</string>
     <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="7274396574659784285">"Acionar a seleção do codec LDAC de áudio\nBluetooth: Qualidade de reprodução"</string>
-    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="2040810756832027227">"Transmissão em fluxo contínuo: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="2040810756832027227">"Stream: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="select_private_dns_configuration_title" msgid="7887550926056143018">"DNS privado"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="3731422918335951912">"Selecionar modo DNS privado"</string>
     <string name="private_dns_mode_off" msgid="7065962499349997041">"Desativado"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Verificar as aplicações instaladas via ADB/ADT para detetar comportamento perigoso."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"São apresentados os dispositivos Bluetooth sem nomes (apenas endereços MAC)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Desativa a funcionalidade de volume absoluto do Bluetooth caso existam problemas de volume com dispositivos remotos, como um volume insuportavelmente alto ou a ausência de controlo."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Ativa a pilha de funcionalidades Bluetooth Gabeldorche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Ativa a pilha de funcionalidades Bluetooth Gabeldorche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Terminal local"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Ativar aplicação terminal que oferece acesso local à shell"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Verificação HDCP"</string>
diff --git a/packages/SettingsLib/res/values-pt/arrays.xml b/packages/SettingsLib/res/values-pt/arrays.xml
index 4e23c19..4658ffd 100644
--- a/packages/SettingsLib/res/values-pt/arrays.xml
+++ b/packages/SettingsLib/res/values-pt/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (padrão)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Usar seleção do sistema (padrão)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 4cccad4..8c03616 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Ativar Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Versão do Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Selecionar versão do Bluetooth AVRCP"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Versão MAP do Bluetooth"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Selecionar versão MAP do Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Codec de áudio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Acionar codec de áudio Bluetooth\nSeleção"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Taxa de amostra do áudio Bluetooth"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Verificar comportamento nocivo em apps instalados via ADB/ADT"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Dispositivos Bluetooth sem nomes (somente endereços MAC) serão exibidos"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Desativa o recurso Bluetooth de volume absoluto em caso de problemas com o volume em dispositivos remotos, como volume excessivamente alto ou falta de controle"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Ativa a pilha de recursos Bluetooth Gabeldorsche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Ativa a pilha de recursos Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Terminal local"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Ativar o app terminal que oferece acesso ao shell local"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Verificação HDCP"</string>
diff --git a/packages/SettingsLib/res/values-ro/arrays.xml b/packages/SettingsLib/res/values-ro/arrays.xml
index befb771..5d25101 100644
--- a/packages/SettingsLib/res/values-ro/arrays.xml
+++ b/packages/SettingsLib/res/values-ro/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (prestabilit)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Folosiți selectarea sistemului (prestabilit)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index a742932..387441f 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Activați Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Versiunea AVRCP pentru Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Selectați versiunea AVRCP pentru Bluetooth"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Versiunea MAP pentru Bluetooth"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Selectați versiunea MAP pentru Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Codec audio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Declanșați codecul audio Bluetooth\nSelecție"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Rată de eșantionare audio Bluetooth"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Verificați aplicațiile instalate utilizând ADB/ADT, pentru a detecta un comportament dăunător."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Vor fi afișate dispozitivele Bluetooth fără nume (numai adresele MAC)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Dezactivează funcția Bluetooth de volum absolut în cazul problemelor de volum apărute la dispozitivele la distanță, cum ar fi volumul mult prea ridicat sau lipsa de control asupra acestuia."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Activează setul de funcții Bluetooth Gabeldorche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Activează setul de funcții Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Aplicație terminal locală"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Activați aplicația terminal care oferă acces la shell local"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Verificare HDCP"</string>
diff --git a/packages/SettingsLib/res/values-ru/arrays.xml b/packages/SettingsLib/res/values-ru/arrays.xml
index d0d04d6..f5367a4 100644
--- a/packages/SettingsLib/res/values-ru/arrays.xml
+++ b/packages/SettingsLib/res/values-ru/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (по умолчанию)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Выбор системы (по умолчанию)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 769b5f3..361e29f 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Включить Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Версия Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Выберите версию Bluetooth AVRCP"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Версия Bluetooth MAP"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Выберите версию Bluetooth MAP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Аудиокодек Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Запустить аудиокодек для Bluetooth\nВыбор"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Частота дискретизации аудио Bluetooth"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Выполнять проверку безопасности приложений при установке через ADB/ADT"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Показывать Bluetooth-устройства без названий (только с MAC-адресами)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Отключить абсолютный уровень громкости Bluetooth при возникновении проблем на удаленных устройствах, например при слишком громком звучании или невозможности контролировать настройку"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Включить стек Bluetooth Gabeldorche"</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Включить стек Bluetooth Gabeldorsche"</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Локальный терминальный доступ"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Разрешить терминальный доступ к локальной оболочке"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Проверка HDCP"</string>
diff --git a/packages/SettingsLib/res/values-si/arrays.xml b/packages/SettingsLib/res/values-si/arrays.xml
index 4764d47..f8c871e 100644
--- a/packages/SettingsLib/res/values-si/arrays.xml
+++ b/packages/SettingsLib/res/values-si/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (පෙරනිමි)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"පද්ධති තේරීම භාවිත කරන්න (පෙරනිමි)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 1d925bf..faa848f 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche සබල කරන්න"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"බ්ලූටූත් AVRCP අනුවාදය"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"බ්ලූටූත් AVRCP අනුවාදය තෝරන්න"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetooth MAP අනුවාදය"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Bluetooth MAP අනුවාදය තෝරන්න"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"බ්ලූටූත් ශ්‍රව්‍ය Codec"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"බ්ලූටූත් ශ්‍රව්‍ය කෝඩෙක් ක්‍රියාරම්භ කරන්න\nතෝරා ගැනීම"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"බ්ලූටූත් ශ්‍රව්‍ය නියැදි අනුපාතය"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ADB/ADT හරහා ස්ථාපනය වූ යෙදුම්, විනාශකාරී ක්‍රියාවන් ඇත්දැයි පරික්ෂාකර බලන්න."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"නම් නොමැති බ්ලූටූත් උපාංග (MAC ලිපින පමණි) සංදර්ශනය කරනු ඇත"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"පිළිගත නොහැකි ලෙස වැඩි හඩ පරිමාව හෝ පාලනය නොමැති වීම යනාදී දුරස්ථ උපාංග සමගින් වන හඬ පරිමා ගැටලුවලදී බ්ලූටූත් නිරපේක්ෂ හඬ පරිමා විශේෂාංගය අබල කරයි."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"බ්ලූටූත් Gabeldorche විශේෂාංග අට්ටිය සබල කරයි."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Bluetooth Gabeldorsche විශේෂාංග අට්ටිය සබල කරයි."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"අභ්‍යන්තර අන්තය"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"දේශීය ෂෙල් ප්‍රවේශනය පිරිනමන ටර්මිනල් යෙදුම සබල කරන්න"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP පරික්ෂාව"</string>
diff --git a/packages/SettingsLib/res/values-sk/arrays.xml b/packages/SettingsLib/res/values-sk/arrays.xml
index 427ee45..f862d88 100644
--- a/packages/SettingsLib/res/values-sk/arrays.xml
+++ b/packages/SettingsLib/res/values-sk/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (predvolené)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Použiť voľbu systému (predvolené)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index e022c36..2035d88c 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Povoliť Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Verzia rozhrania Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Zvoľte verziu rozhrania Bluetooth AVRCP"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Verzia profilu Bluetooth MAP"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Výber verzie profilu Bluetooth MAP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth Audio – kodek"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Spustiť zvukový kodek Bluetooth\nVýber"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth Audio – vzorkovacia frekvencia"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Kontrolovať škodlivosť aplikácií nainštalovaných pomocou nástroja ADB alebo ADT"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Zariadenia Bluetooth sa budú zobrazovať bez názvov (iba adresy MAC)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Umožňuje zakázať funkciu absolútnej hlasitosti rozhrania Bluetooth v prípade problémov s hlasitosťou vo vzdialených zariadeniach, ako je napríklad neprijateľne vysoká hlasitosť alebo absencia ovládacích prvkov."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Umožňuje povoliť skupiny funkcií Bluetooth Gabeldorche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Umožňuje povoliť skupinu funkcií Bluetooth Gabeldorche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Miestny terminál"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Povoliť terminálovú apl. na miestny prístup k prostrediu shell"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Kontrola HDCP"</string>
diff --git a/packages/SettingsLib/res/values-sl/arrays.xml b/packages/SettingsLib/res/values-sl/arrays.xml
index d946316..eb86074 100644
--- a/packages/SettingsLib/res/values-sl/arrays.xml
+++ b/packages/SettingsLib/res/values-sl/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (privzeto)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Uporabi sistemsko izbiro (privzeto)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index efd7c08..2889619 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Omogoči Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Različica profila AVRCP za Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Izberite različico profila AVRCP za Bluetooth"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Različica profila MAP za Bluetooth"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Izbira različice profila MAP za Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Zvočni kodek za Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Sproži zvočni kodek za Bluetooth\nIzbor"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Hitrost vzorčenja zvoka prek Bluetootha"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Preveri, ali so aplikacije, nameščene prek ADB/ADT, škodljive."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Prikazane bodo naprave Bluetooth brez imen (samo z naslovi MAC)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Onemogoči funkcijo absolutne glasnosti za Bluetooth, če pride do težav z glasnostjo z oddaljenimi napravami, kot je nesprejemljivo visoka glasnost ali pomanjkanje nadzora."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Omogoči sklad funkcij Bluetooth Gabeldorche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Omogoči sklad funkcij Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Lokalni terminal"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Omogočanje terminalske aplikacije za dostop do lokalne lupine"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Preverjanje HDCP"</string>
diff --git a/packages/SettingsLib/res/values-sq/arrays.xml b/packages/SettingsLib/res/values-sq/arrays.xml
index 26ba289..1363e83 100644
--- a/packages/SettingsLib/res/values-sq/arrays.xml
+++ b/packages/SettingsLib/res/values-sq/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (parazgjedhja)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Përdor përzgjedhjen e sistemit (e parazgjedhur)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index c7c4230..ccd4e30 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Aktivizo Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Versioni AVRCP i Bluetooth-it"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Zgjidh versionin AVRCP të Bluetooth-it"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Versioni MAP i Bluetooth-it"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Zgjidh versionin MAP të Bluetooth-it"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Kodeku Bluetooth Audio"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Aktivizo kodekun e audios me Bluetooth\nZgjedhja"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Shpejtësia e shembullit të Bluetooth Audio"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Kontrollo aplikacionet e instaluara nëpërmjet ADB/ADT për sjellje të dëmshme."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Pajisjet me Bluetooth do të shfaqen pa emra (vetëm adresat MAC)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Çaktivizon funksionin e volumit absolut të Bluetooth në rast të problemeve të volumit me pajisjet në largësi, si p.sh. një volum i lartë i papranueshëm ose mungesa e kontrollit."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Aktivizon grupin e veçorive të Bluetooth Gabeldorche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Aktivizon grupin e veçorive të Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Terminali lokal"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Aktivizo aplikacionin terminal që ofron qasje në guaskën lokale"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Kontrolli HDCP"</string>
diff --git a/packages/SettingsLib/res/values-sr/arrays.xml b/packages/SettingsLib/res/values-sr/arrays.xml
index c543ac1..a4e9156 100644
--- a/packages/SettingsLib/res/values-sr/arrays.xml
+++ b/packages/SettingsLib/res/values-sr/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (подразумевано)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Користи избор система (подразумевано)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index a395d7b..08e2bc8 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Омогући Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Верзија Bluetooth AVRCP-а"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Изаберите верзију Bluetooth AVRCP-а"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Верзија Bluetooth MAP-а"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Изаберите верзију Bluetooth MAP-а"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth аудио кодек"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Изаберите Bluetooth аудио кодек\n"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Брзина узорковања за Bluetooth аудио"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Проверава да ли су апликације инсталиране преко ADB-а/ADT-а штетне."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Биће приказани Bluetooth уређаји без назива (само са MAC адресама)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Онемогућава главно подешавање јачине звука на Bluetooth уређају у случају проблема са јачином звука на даљинским уређајима, као што су изузетно велика јачина звука или недостатак контроле."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Омогућава групу Bluetooth Gabeldorche функција."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Омогућава групу Bluetooth Gabeldorsche функција."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Локални терминал"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Омогући апл. терминала за приступ локалном командном окружењу"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP провера"</string>
diff --git a/packages/SettingsLib/res/values-sv/arrays.xml b/packages/SettingsLib/res/values-sv/arrays.xml
index c31b80c..b5b1186a 100644
--- a/packages/SettingsLib/res/values-sv/arrays.xml
+++ b/packages/SettingsLib/res/values-sv/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (standard)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Använd systemval (standardinställning)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index f021cc2..c0cdbc9 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Aktivera Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"AVRCP-version för Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Välj AVRCP-version för Bluetooth"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"MAP-version för Bluetooth"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Välj MAP-version för Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Ljudkodek för Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Aktivera ljudkodek för Bluetooth\nVal"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Samplingsfrekvens för Bluetooth-ljud"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Kontrollera om appar som installeras via ADB/ADT kan vara skadliga."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth-enheter utan namn (enbart MAC-adresser) visas"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Inaktivera Bluetooth-funktionen Absolute volume om det skulle uppstå problem med volymen på fjärrenheter, t.ex. alldeles för hög volym eller brist på kontroll."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Aktiverar funktionsgruppen Bluetooth Gabeldorche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Aktiverar funktionsgruppen Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Lokal terminal"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Aktivera en terminalapp som ger åtkomst till hyllor lokalt"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP-kontroll"</string>
diff --git a/packages/SettingsLib/res/values-sw/arrays.xml b/packages/SettingsLib/res/values-sw/arrays.xml
index ff48858..a29b74e 100644
--- a/packages/SettingsLib/res/values-sw/arrays.xml
+++ b/packages/SettingsLib/res/values-sw/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"RAMANI YA 1.2 (Chaguomsingi)"</item>
+    <item msgid="6817922176194686449">"RAMANI YA 1.3"</item>
+    <item msgid="3423518690032737851">"RAMANI YA 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"ramani ya 12"</item>
+    <item msgid="7073042887003102964">"ramani ya 13"</item>
+    <item msgid="8147982633566548515">"ramani ya 14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Tumia Uteuzi wa Mfumo (Chaguomsingi)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 42422fb..f00dea3 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Washa Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Toleo la Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Chagua Toleo la Bluetooth AVRCP"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Toleo la Ramani ya Bluetooth"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Chagua Toleo la Ramani ya Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Kodeki ya Sauti ya Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Weka Kodeki ya Sauti ya Bluetooth\nUteuzi"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Kiwango cha Sampuli ya Sauti ya Bluetooth"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Kagua iwapo programu zilizosakinishwa kupitia ADB/ADT zina tabia ya kudhuru."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Itaonyesha vifaa vya Bluetooth bila majina (anwani za MAC pekee)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Huzima kipengele cha Bluetooth cha sauti kamili kunapotokea matatizo ya sauti katika vifaa vya mbali kama vile sauti ya juu mno au inaposhindikana kuidhibiti."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Huwasha rafu ya kipengele cha Bluetooth Gabeldorche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Huwasha rafu ya kipengele ya Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Kituo cha karibu"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Washa programu ya mwisho inayotoa ufikiaji mkuu wa karibu"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Inakagua HDCP"</string>
diff --git a/packages/SettingsLib/res/values-ta/arrays.xml b/packages/SettingsLib/res/values-ta/arrays.xml
index 5668b6d..0f19148 100644
--- a/packages/SettingsLib/res/values-ta/arrays.xml
+++ b/packages/SettingsLib/res/values-ta/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (இயல்பாக)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"சாதனத் தேர்வைப் பயன்படுத்து (இயல்பு)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 295399d..52e0363 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -227,10 +227,11 @@
     <string name="tethering_hardware_offload" msgid="4116053719006939161">"வன்பொருள் விரைவுப்படுத்துதல் இணைப்பு முறை"</string>
     <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"பெயர்கள் இல்லாத புளூடூத் சாதனங்களைக் காட்டு"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"அப்சல்யூட் ஒலியளவு அம்சத்தை முடக்கு"</string>
-    <!-- no translation found for bluetooth_enable_gabeldorsche (9131730396242883416) -->
-    <skip />
+    <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorscheவை இயக்கு"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"புளூடூத் AVRCP பதிப்பு"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"புளூடூத் AVRCP பதிப்பைத் தேர்ந்தெடு"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"புளூடூத்தின் MAP பதிப்பு"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"புளூடூத்தின் MAP பதிப்பைத் தேர்வுசெய்க"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"புளூடூத் ஆடியோ கோடெக்"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"புளூடூத் ஆடியோ கோடெக்கைத் தொடங்கு\nதேர்வு"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"புளூடூத் ஆடியோ சாம்பிள் ரேட்"</string>
@@ -277,8 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"தீங்கு விளைவிக்கும் செயல்பாட்டை அறிய ADB/ADT மூலம் நிறுவப்பட்ட ஆப்ஸைச் சரிபார்."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"பெயர்கள் இல்லாத புளூடூத் சாதனங்கள் (MAC முகவரிகள் மட்டும்) காட்டப்படும்"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"மிகவும் அதிகமான ஒலியளவு அல்லது கட்டுப்பாடு இழப்பு போன்ற தொலைநிலைச் சாதனங்களில் ஏற்படும் ஒலி தொடர்பான சிக்கல்கள் இருக்கும் சமயங்களில், புளூடூத் அப்சல்யூட் ஒலியளவு அம்சத்தை முடக்கும்."</string>
-    <!-- no translation found for bluetooth_enable_gabeldorsche_summary (8472344901097607030) -->
-    <skip />
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"புளூடூத்தின் Gabeldorsche அம்சங்களை இயக்கும்."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"அக முனையம்"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"அக ஷெல் அணுகலை வழங்கும் இறுதிப் ஆப்ஸை இயக்கு"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP சரிபார்ப்பு"</string>
diff --git a/packages/SettingsLib/res/values-te/arrays.xml b/packages/SettingsLib/res/values-te/arrays.xml
index 70068bf..23256ee 100644
--- a/packages/SettingsLib/res/values-te/arrays.xml
+++ b/packages/SettingsLib/res/values-te/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (డిఫాల్ట్)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"సిస్టమ్ ఎంపికను ఉపయోగించండి (డిఫాల్ట్)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index f92b8af..a39c4e1 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorscheను ఎనేబుల్ చేయి"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"బ్లూటూత్ AVRCP వెర్షన్"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"బ్లూటూత్ AVRCP సంస్కరణను ఎంచుకోండి"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"బ్లూటూత్ MAP వెర్షన్‌"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"బ్లూటూత్ MAP వెర్షన్‌ను ఎంచుకోండి"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"బ్లూటూత్ ఆడియో కోడెక్"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"బ్లూటూత్ ఆడియో కోడెక్‌ని సక్రియం చేయండి\nఎంపిక"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"బ్లూటూత్ ఆడియో నమూనా రేట్"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"హానికరమైన ప్రవర్తన కోసం ADB/ADT ద్వారా ఇన్‌స్టాల్ చేయబడిన యాప్‌లను తనిఖీ చేయి."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"పేర్లు (MAC చిరునామాలు మాత్రమే) లేని బ్లూటూత్ పరికరాలు ప్రదర్శించబడతాయి"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"రిమోట్ పరికరాల్లో ఆమోదించలేని స్థాయిలో అధిక వాల్యూమ్ ఉండటం లేదా వాల్యూమ్ నియంత్రణ లేకపోవడం వంటి సమస్యలు ఉంటే బ్లూటూత్ సంపూర్ణ వాల్యూమ్ ఫీచర్‌ని నిలిపివేస్తుంది."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"బ్లూటూత్ ఫీచర్ స్ట్యాక్‌ను ఎనేబుల్ చేస్తుంది."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"బ్లూటూత్ Gabeldorsche ఫీచర్ స్ట్యాక్‌ను ఎనేబుల్ చేస్తుంది."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"స్థానిక టెర్మినల్"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"స్థానిక షెల్ ప్రాప్యతను అందించే టెర్మినల్ అనువర్తనాన్ని ప్రారంభించు"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP తనిఖీ"</string>
diff --git a/packages/SettingsLib/res/values-th/arrays.xml b/packages/SettingsLib/res/values-th/arrays.xml
index 20333b7..8aac165 100644
--- a/packages/SettingsLib/res/values-th/arrays.xml
+++ b/packages/SettingsLib/res/values-th/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (ค่าเริ่มต้น)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"ใช้การเลือกของระบบ (ค่าเริ่มต้น)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 19ae491..635d77a 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"เปิดใช้ Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"เวอร์ชันของบลูทูธ AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"เลือกเวอร์ชันของบลูทูธ AVRCP"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"เวอร์ชัน MAP ของบลูทูธ"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"เลือกเวอร์ชัน MAP ของบลูทูธ"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"ตัวแปลงสัญญาณเสียงบลูทูธ"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ทริกเกอร์การเลือกตัวแปลงรหัส\nเสียงบลูทูธ"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"อัตราตัวอย่างเสียงบลูทูธ"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ตรวจสอบแอปที่ติดตั้งผ่าน ADB/ADT เพื่อตรวจดูพฤติกรรมที่เป็นอันตราย"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"ระบบจะแสดงอุปกรณ์บลูทูธที่ไม่มีชื่อ (มีเฉพาะที่อยู่ MAC)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"ปิดใช้ฟีเจอร์การควบคุมระดับเสียงของอุปกรณ์อื่นผ่านบลูทูธในกรณีที่มีปัญหาเกี่ยวกับระดับเสียงของอุปกรณ์ระยะไกล เช่น ระดับเสียงที่ดังเกินไปหรือระดับเสียงที่ไม่มีการควบคุม"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"เปิดใช้สแต็กฟีเจอร์ Bluetooth Gabeldorche"</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"เปิดใช้สแต็กฟีเจอร์ Bluetooth Gabeldorsche"</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"เทอร์มินัลในตัวเครื่อง"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"เปิดใช้งานแอปเทอร์มินัลที่ให้การเข้าถึงเชลล์ในตัวเครื่อง"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"การตรวจสอบ HDCP"</string>
diff --git a/packages/SettingsLib/res/values-tl/arrays.xml b/packages/SettingsLib/res/values-tl/arrays.xml
index 4734807..9e08b8f 100644
--- a/packages/SettingsLib/res/values-tl/arrays.xml
+++ b/packages/SettingsLib/res/values-tl/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (Default)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Gamitin ang Pagpili ng System (Default)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index f6dfdba..3f7f0ff 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"I-enable ang Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bersyon ng AVRCP ng Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Pumili ng Bersyon ng AVRCP ng Bluetooth"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bersyon ng MAP ng Bluetooth"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Pumili ng Bersyon ng MAP ng Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth Audio Codec"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"I-trigger ang Pagpili sa Audio Codec ng\nBluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Sample na Rate ng Bluetooth Audio"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Tingnan kung may nakakahamak na pagkilos sa apps na na-install sa pamamagitan ng ADB/ADT."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Ipapakita ang mga Bluetooth device na walang pangalan (mga MAC address lang)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Dini-disable ang absolute volume feature ng Bluetooth kung may mga isyu sa volume ang mga malayong device gaya ng hindi katanggap-tanggap na malakas na volume o kawalan ng kontrol."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Ine-enable ang stack ng feature ng Bluetooth Gabeldorche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Ine-enable ang stack ng feature ng Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Lokal na terminal"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Paganahin ang terminal app na nag-aalok ng lokal na shell access"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Pagsusuring HDCP"</string>
diff --git a/packages/SettingsLib/res/values-tr/arrays.xml b/packages/SettingsLib/res/values-tr/arrays.xml
index ac6e0f5..7ce6c24 100644
--- a/packages/SettingsLib/res/values-tr/arrays.xml
+++ b/packages/SettingsLib/res/values-tr/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (Varsayılan)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Sistem Seçimini Kullan (Varsayılan)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 554d62e..7ad6fcd 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche\'yi etkileştir"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP Sürümü"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Bluetooth AVRCP Sürümünü seçin"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetooth MAP Sürümü"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Bluetooth MAP Sürümünü seçin"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth Ses Codec\'i"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth Ses Codec\'i Tetikleme\nSeçimi"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth Ses Örnek Hızı"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ADB/ADT üzerinden yüklenen uygulamaları zararlı davranışlara karşı denetle."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Adsız Bluetooth cihazları (yalnızca MAC adresleri) gösterilecek"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Uzak cihazda sesin aşırı yüksek olması veya kontrol edilememesi gibi ses sorunları olması ihtimaline karşı Bluetooh mutlak ses özelliğini iptal eder."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Bluetooth Gabeldorche özellik grubunu etkinleştirir."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Bluetooth Gabeldorsche özellik yığınını etkinleştirir."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Yerel terminal"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Yerel kabuk erişimi sunan terminal uygulamasını etkinleştir"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP denetimi"</string>
diff --git a/packages/SettingsLib/res/values-uk/arrays.xml b/packages/SettingsLib/res/values-uk/arrays.xml
index effd496..2d0abe0 100644
--- a/packages/SettingsLib/res/values-uk/arrays.xml
+++ b/packages/SettingsLib/res/values-uk/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (за умовчанням)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Використовувати вибір системи (за умовчанням)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 17f2393..b5dd618 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Увімкнути Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Версія Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Виберіть версію Bluetooth AVRCP"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Версія Bluetooth MAP"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Виберіть версію Bluetooth MAP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Кодек для аудіо Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Активувати кодек для аудіо Bluetooth\nВибір"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Частота вибірки для аудіо Bluetooth"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Перевіряти безпеку додатків, установлених через ADB/ADT."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Пристрої Bluetooth відображатимуться без назв (лише MAC-адреси)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Функція абсолютної гучності Bluetooth вимикається, якщо на віддалених пристроях виникають проблеми, як-от надто висока гучність або втрата контролю."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Вмикає функції Bluetooth Gabeldorche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Вмикає функції Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Локальний термінал"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Увімк. програму-термінал, що надає локальний доступ до оболонки"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Перевірка HDCP"</string>
diff --git a/packages/SettingsLib/res/values-ur/arrays.xml b/packages/SettingsLib/res/values-ur/arrays.xml
index d5a59ac..e056c1c 100644
--- a/packages/SettingsLib/res/values-ur/arrays.xml
+++ b/packages/SettingsLib/res/values-ur/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"‏MAP 1.2 ‏(ڈیفالٹ)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 6830c59..ef9b2a1 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"‏Gabeldorsche فعال کریں"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"‏بلوٹوتھ AVRCP ورژن"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"‏بلوٹوتھ AVRCP ورژن منتخب کریں"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"‏بلوٹوتھ MAP ورژن"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"‏بلوٹوتھ MAP ورژن منتخب کریں"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"بلوٹوتھ آڈیو کوڈیک"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"بلوٹوتھ آڈیو کوڈیک کو ٹریگر کریں\nانتخاب"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"بلوٹوتھ آڈیو کے نمونے کی شرح"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"‏نقصان دہ رویے کے مدنظر ADB/ADT کی معرفت انسٹال شدہ ایپس کی جانچ کریں۔"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"‏بغیر نام والے بلوٹوتھ آلات (صرف MAC پتے) ڈسپلے کئے جائیں گے"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"ریموٹ آلات کے ساتھ والیوم کے مسائل مثلاً نا قابل قبول حد تک بلند والیوم یا کنٹرول نہ ہونے کی صورت میں بلو ٹوتھ مطلق والیوم والی خصوصیت کو غیر فعال کریں۔"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"‏بلوٹوتھ Gabeldorche خصوصیت کے انبار کو فعال کرتا ہے۔"</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"‏بلوٹوتھ Gabeldorsche خصوصیت کے انبار کو فعال کرتا ہے۔"</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"مقامی ٹرمینل"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"مقامی شیل رسائی پیش کرنے والی ٹرمینل ایپ فعال کریں"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"‏HDCP چیکنگ"</string>
diff --git a/packages/SettingsLib/res/values-uz/arrays.xml b/packages/SettingsLib/res/values-uz/arrays.xml
index 4d30e46..892ebe0 100644
--- a/packages/SettingsLib/res/values-uz/arrays.xml
+++ b/packages/SettingsLib/res/values-uz/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (Standart)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Tizim tanlovi (birlamchi)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 52ec545..b202d64 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche funksiyasini yoqish"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP versiyasi"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Bluetooth AVRCP versiyasini tanlang"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetooth MAP versiyasi"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Bluetooth MAP versiyasini tanlang"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth audio kodeki"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Bluetooth orqali uzatish uchun audiokodek\nTanlash"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Bluetooth audio namunasi chastotasi"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ADB/ADT orqali o‘rnatilgan ilovalar xavfsizligini tekshiring"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth qurilmalari nomsiz (faqat MAC manzillari) ko‘rsatiladi"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Masofadan ulanadigan qurilmalar bilan muammolar yuz berganda, jumladan, juda baland ovoz yoki sozlamalarni boshqarib bo‘lmaydigan holatlarda Bluetooth ovozi balandligining mutlaq darajasini o‘chirib qo‘yadi."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Bluetooth Gabeldorche funksiyasini ishga tushiradi."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Bluetooth Gabeldorsche funksiyasini ishga tushiradi."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Mahalliy terminal"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Mahalliy terminalga kirishga ruxsat beruvchi terminal ilovani faollashtirish"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP tekshiruvi"</string>
diff --git a/packages/SettingsLib/res/values-vi/arrays.xml b/packages/SettingsLib/res/values-vi/arrays.xml
index edfe89e..db29bc8 100644
--- a/packages/SettingsLib/res/values-vi/arrays.xml
+++ b/packages/SettingsLib/res/values-vi/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (Mặc định)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Sử dụng lựa chọn của hệ thống (Mặc định)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 2a12464..cda42d3 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Bật tính năng Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Phiên bản Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Chọn phiên bản Bluetooth AVRCP"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Phiên bản Bluetooth MAP"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Chọn phiên bản Bluetooth MAP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Codec âm thanh Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Kích hoạt chế độ chọn codec\nâm thanh Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Tốc độ lấy mẫu âm thanh Bluetooth"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Kiểm tra các ứng dụng được cài đặt qua ADB/ADT để xem có hoạt động gây hại hay không."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Các thiết bị Bluetooth không có tên (chỉ có địa chỉ MAC) sẽ được hiển thị"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Vô hiệu hóa tính năng âm lượng tuyệt đối qua Bluetooth trong trường hợp xảy ra sự cố về âm lượng với các thiết bị từ xa, chẳng hạn như âm lượng lớn không thể chấp nhận được hoặc thiếu kiểm soát."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Bật ngăn xếp tính năng Bluetooth Gabeldorche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Bật ngăn xếp tính năng Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Dòng lệnh cục bộ"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Bật ứng dụng dòng lệnh cung cấp quyền truy cập vỏ cục bộ"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Kiểm tra HDCP"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/arrays.xml b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
index 992e3e0..3016f65 100644
--- a/packages/SettingsLib/res/values-zh-rCN/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2(默认)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"使用系统选择(默认)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 3fe925b..418370b 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"启用“Gabeldorsche”"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"蓝牙 AVRCP 版本"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"选择蓝牙 AVRCP 版本"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"蓝牙 MAP 版本"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"选择蓝牙 MAP 版本"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"蓝牙音频编解码器"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"触发蓝牙音频编解码器\n选择"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"蓝牙音频采样率"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"检查通过 ADB/ADT 安装的应用是否存在有害行为。"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"系统将显示没有名称(只有 MAC 地址)的蓝牙设备"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"停用蓝牙绝对音量功能,即可避免在连接到远程设备时出现音量问题(例如音量高得让人无法接受或无法控制音量等)。"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"启用“蓝牙 Gabeldorche”功能堆栈。"</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"启用“蓝牙 Gabeldorsche”功能堆栈。"</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"本地终端"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"启用终端应用,以便在本地访问 Shell"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP 检查"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/arrays.xml b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
index d91e61e..0b57af9 100644
--- a/packages/SettingsLib/res/values-zh-rHK/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (預設)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"使用系統選擇 (預設)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index ed6d505..79b5579 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"啟用 Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"藍牙 AVRCP 版本"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"選擇藍牙 AVRCP 版本"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"藍牙 MAP 版本"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"選擇藍牙 MAP 版本"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"藍牙音訊編解碼器"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"觸發藍牙音訊編解碼器\n選項"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"藍牙音訊取樣率"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"透過 ADB/ADT 檢查安裝的應用程式有否有害的行為。"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"系統將顯示沒有名稱 (只有 MAC 位址) 的藍牙裝置"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"連線至遠端裝置時,如發生音量過大或無法控制音量等問題,請停用藍牙絕對音量功能。"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"啟用藍牙 Gabeldorche 功能組合。"</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"啟用藍牙 Gabeldorsche 功能組合。"</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"本機終端機"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"啟用可提供本機命令介面存取權的終端機應用程式"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP 檢查"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/arrays.xml b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
index f39ab84..7b25772 100644
--- a/packages/SettingsLib/res/values-zh-rTW/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"avrcp15"</item>
     <item msgid="1963366694959681026">"avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"MAP 1.2 (預設)"</item>
+    <item msgid="6817922176194686449">"MAP 1.3"</item>
+    <item msgid="3423518690032737851">"MAP 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"map12"</item>
+    <item msgid="7073042887003102964">"map13"</item>
+    <item msgid="8147982633566548515">"map14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"系統自動選擇 (預設)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 45866d4..47ab764 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"啟用 Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"藍牙 AVRCP 版本"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"選取藍牙 AVRCP 版本"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"藍牙 MAP 版本"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"選取 Bluetooth MAP 版本"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"藍牙音訊轉碼器"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"觸發藍牙音訊轉碼器\n選項"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"藍牙音訊取樣率"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"檢查透過 ADB/ADT 安裝的應用程式是否具有有害行為。"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"系統會顯示沒有名稱 (僅具有 MAC 位址) 的藍牙裝置"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"只要停用藍牙絕對音量功能,即可避免在連線到遠端裝置時,發生音量過大或無法控制音量等問題。"</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"啟用藍牙 Gabeldorsche 功能堆疊。"</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"啟用藍牙 Gabeldorsche 功能堆疊。"</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"本機終端機"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"啟用可提供本機命令介面存取權的終端機應用程式"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP 檢查"</string>
diff --git a/packages/SettingsLib/res/values-zu/arrays.xml b/packages/SettingsLib/res/values-zu/arrays.xml
index 5c93cc5..517d1c8 100644
--- a/packages/SettingsLib/res/values-zu/arrays.xml
+++ b/packages/SettingsLib/res/values-zu/arrays.xml
@@ -75,6 +75,16 @@
     <item msgid="4398977131424970917">"I-avrcp15"</item>
     <item msgid="1963366694959681026">"I-avrcp16"</item>
   </string-array>
+  <string-array name="bluetooth_map_versions">
+    <item msgid="8786402640610987099">"IMEPHU 1.2 (Okuzenzakalelayo)"</item>
+    <item msgid="6817922176194686449">"IMEPHU 1.3"</item>
+    <item msgid="3423518690032737851">"IMEPHU 1.4"</item>
+  </string-array>
+  <string-array name="bluetooth_map_version_values">
+    <item msgid="1164651830068248391">"Imephu12"</item>
+    <item msgid="7073042887003102964">"Imephu13"</item>
+    <item msgid="8147982633566548515">"Imephu14"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="2494959071796102843">"Sebenzisa ukukhetha kwesistimu (Okuzenzakalelayo)"</item>
     <item msgid="4055460186095649420">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 8b004f9..87f45de 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -230,6 +230,8 @@
     <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Nika amandla i-Gabeldorsche"</string>
     <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Inguqulo ye-Bluetooth ye-AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Khetha inguqulo ye-Bluetooth AVRCP"</string>
+    <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Inguqulo ye-Bluetooth MAP"</string>
+    <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Khetha inguqulo ye-Bluetooth MAP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"I-Bluetooth Audio Codec"</string>
     <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Qalisa i-codec ye-bluetooth yomsindo\nUkukhethwa"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Isilinganiso sesampula yomsindo we-Bluetooth"</string>
@@ -276,7 +278,7 @@
     <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Hlola izinhlelo zokusebenza ezifakiwe nge-ADB/ADT ngokuziphatha okuyingozi."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Amadivayisi e-Bluetooth anganawo amagama (Amakheli e-MAC kuphela) azoboniswa"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Ikhubaza isici esiphelele sevolumu ye-Bluetooth uma kuba nezinkinga zevolumu ngamadivayisi esilawuli kude ezifana nevolumu ephezulu noma eshoda ngokulawuleka."</string>
-    <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Inika amandla isitaki sesici se-Bluetooth Gabeldorche."</string>
+    <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Inika amandla isitaki sesici se-Bluetooth Gabeldorsche."</string>
     <string name="enable_terminal_title" msgid="3834790541986303654">"Itheminali yasendaweni"</string>
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Nika amandla uhlelo lokusebenza letheminali olunikeza ukufinyelela kwasendaweni kwe-shell"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Ihlola i-HDCP"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractImsStatusPreferenceController.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractImsStatusPreferenceController.java
index 4c3e605..d427f7a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractImsStatusPreferenceController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractImsStatusPreferenceController.java
@@ -23,7 +23,9 @@
 import android.os.PersistableBundle;
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
+import android.telephony.ims.ImsMmTelManager;
+import android.telephony.ims.RegistrationManager;
+import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
@@ -32,15 +34,26 @@
 import com.android.settingslib.R;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Consumer;
+
 /**
  * Preference controller for IMS status
  */
 public abstract class AbstractImsStatusPreferenceController
         extends AbstractConnectivityPreferenceController {
 
+    private static final String LOG_TAG = "AbstractImsPrefController";
+
     @VisibleForTesting
     static final String KEY_IMS_REGISTRATION_STATE = "ims_reg_state";
 
+    private static final long MAX_THREAD_BLOCKING_TIME_MS = 2000;
+
     private static final String[] CONNECTIVITY_INTENTS = {
             BluetoothAdapter.ACTION_STATE_CHANGED,
             ConnectivityManager.CONNECTIVITY_ACTION,
@@ -57,8 +70,9 @@
 
     @Override
     public boolean isAvailable() {
-        CarrierConfigManager configManager = mContext.getSystemService(CarrierConfigManager.class);
-        int subId = SubscriptionManager.getDefaultDataSubscriptionId();
+        final CarrierConfigManager configManager =
+                mContext.getSystemService(CarrierConfigManager.class);
+        final int subId = SubscriptionManager.getDefaultDataSubscriptionId();
         PersistableBundle config = null;
         if (configManager != null) {
             config = configManager.getConfigForSubId(subId);
@@ -86,11 +100,57 @@
 
     @Override
     protected void updateConnectivity() {
-        int subId = SubscriptionManager.getDefaultDataSubscriptionId();
-        if (mImsStatus != null) {
-            TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
-            mImsStatus.setSummary((tm != null && tm.isImsRegistered(subId)) ?
-                    R.string.ims_reg_status_registered : R.string.ims_reg_status_not_registered);
+        if (mImsStatus == null) {
+            return;
+        }
+        final int subId = SubscriptionManager.getDefaultDataSubscriptionId();
+        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+            mImsStatus.setSummary(R.string.ims_reg_status_not_registered);
+            return;
+        }
+        final ExecutorService executors = Executors.newSingleThreadExecutor();
+        final StateCallback stateCallback = new StateCallback();
+
+        final ImsMmTelManager imsMmTelManager = ImsMmTelManager.createForSubscriptionId(subId);
+        try {
+            imsMmTelManager.getRegistrationState(executors, stateCallback);
+        } catch (Exception ex) {
+        }
+
+        mImsStatus.setSummary(stateCallback.waitUntilResult()
+                ? R.string.ims_reg_status_registered : R.string.ims_reg_status_not_registered);
+
+        try {
+            executors.shutdownNow();
+        } catch (Exception exception) {
+        }
+    }
+
+    private final class StateCallback extends AtomicBoolean implements Consumer<Integer> {
+        private StateCallback() {
+            super(false);
+            mSemaphore = new Semaphore(0);
+        }
+
+        private final Semaphore mSemaphore;
+
+        public void accept(Integer state) {
+            set(state == RegistrationManager.REGISTRATION_STATE_REGISTERED);
+            try {
+                mSemaphore.release();
+            } catch (Exception ex) {
+            }
+        }
+
+        public boolean waitUntilResult() {
+            try {
+                if (!mSemaphore.tryAcquire(MAX_THREAD_BLOCKING_TIME_MS, TimeUnit.MILLISECONDS)) {
+                    Log.w(LOG_TAG, "IMS registration state query timeout");
+                    return false;
+                }
+            } catch (Exception ex) {
+            }
+            return get();
         }
     }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
index 05a6ce4..9d7e2c8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
@@ -38,7 +38,7 @@
         final SubscriptionManager subscriptionManager = context.getSystemService(
                 SubscriptionManager.class);
         final NetworkTemplate mobileAll = NetworkTemplate.buildTemplateMobileAll(
-                telephonyManager.createForSubscriptionId(subId).getSubscriberId());
+                telephonyManager.getSubscriberId());
 
         if (!subscriptionManager.isActiveSubscriptionId(subId)) {
             Log.i(TAG, "Subscription is not active: " + subId);
diff --git a/packages/SettingsProvider/Android.bp b/packages/SettingsProvider/Android.bp
index 96a98dc..d67bd8d 100644
--- a/packages/SettingsProvider/Android.bp
+++ b/packages/SettingsProvider/Android.bp
@@ -30,7 +30,7 @@
         "src/com/android/providers/settings/SettingsBackupAgent.java",
         "src/com/android/providers/settings/SettingsState.java",
         "src/com/android/providers/settings/SettingsHelper.java",
-        "src/com/android/providers/settings/WifiSoftApBandChangedNotifier.java",
+        "src/com/android/providers/settings/WifiSoftApConfigChangedNotifier.java",
     ],
     static_libs: [
         "androidx.test.rules",
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index fb558ab..cdf9728 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -968,18 +968,14 @@
     }
 
     private void restoreSoftApConfiguration(byte[] data) {
-        SoftApConfiguration config = mWifiManager.restoreSoftApBackupData(data);
-        if (config != null) {
-            int originalApBand = config.getBand();
+        SoftApConfiguration configInCloud = mWifiManager.restoreSoftApBackupData(data);
+        if (configInCloud != null) {
             if (DEBUG) Log.d(TAG, "Successfully unMarshaled SoftApConfiguration ");
-
-            // Depending on device hardware, we may need to notify the user of a setting change for
-            // the apBand preference
-            boolean dualMode = mWifiManager.isDualModeSupported();
-            int storedApBand = mWifiManager.getSoftApConfiguration().getBand();
-            if (dualMode && storedApBand != originalApBand) {
+            // Depending on device hardware, we may need to notify the user of a setting change
+            SoftApConfiguration storedConfig = mWifiManager.getSoftApConfiguration();
+            if (!storedConfig.equals(configInCloud)) {
                 Log.d(TAG, "restored ap configuration requires a conversion, notify the user");
-                WifiSoftApBandChangedNotifier.notifyUserOfApBandConversion(this);
+                WifiSoftApConfigChangedNotifier.notifyUserOfConfigConversion(this);
             }
         }
     }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/WifiSoftApBandChangedNotifier.java b/packages/SettingsProvider/src/com/android/providers/settings/WifiSoftApConfigChangedNotifier.java
similarity index 93%
rename from packages/SettingsProvider/src/com/android/providers/settings/WifiSoftApBandChangedNotifier.java
rename to packages/SettingsProvider/src/com/android/providers/settings/WifiSoftApConfigChangedNotifier.java
index d0d4956..1ee5f90 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/WifiSoftApBandChangedNotifier.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/WifiSoftApConfigChangedNotifier.java
@@ -27,17 +27,17 @@
 import com.android.internal.notification.SystemNotificationChannels;
 
 /**
- * Helper class for sending notifications when the user's Soft AP Band was changed upon restore.
+ * Helper class for sending notifications when the user's Soft AP config was changed upon restore.
  */
-public class WifiSoftApBandChangedNotifier {
-    private WifiSoftApBandChangedNotifier() {}
+public class WifiSoftApConfigChangedNotifier {
+    private WifiSoftApConfigChangedNotifier() {}
 
     /**
-     * Send a notification informing the user that their' Soft AP Band was changed upon restore.
+     * Send a notification informing the user that their' Soft AP Config was changed upon restore.
      * When the user taps on the notification, they are taken to the Wifi Tethering page in
      * Settings.
      */
-    public static void notifyUserOfApBandConversion(Context context) {
+    public static void notifyUserOfConfigConversion(Context context) {
         NotificationManager notificationManager =
                 context.getSystemService(NotificationManager.class);
 
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 0bcadce..6aeb0a1 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -174,6 +174,9 @@
     <!-- Adding Quick Settings tiles -->
     <uses-permission android:name="android.permission.BIND_QUICK_SETTINGS_TILE" />
 
+    <!-- Access Quick Access Wallet cards -->
+    <uses-permission android:name="android.permission.BIND_QUICK_ACCESS_WALLET_SERVICE" />
+
     <!-- Adding Controls to SystemUI -->
     <uses-permission android:name="android.permission.BIND_CONTROLS" />
 
diff --git a/packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java b/packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java
new file mode 100644
index 0000000..2f8ef2d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java
@@ -0,0 +1,216 @@
+/*
+ * 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.keyguard;
+
+import android.annotation.Nullable;
+import android.app.admin.IKeyguardCallback;
+import android.app.admin.IKeyguardClient;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
+import android.view.SurfaceControl;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.ViewGroup;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Encapsulates all logic for secondary lockscreen state management.
+ */
+public class AdminSecondaryLockScreenController {
+    private static final String TAG = "AdminSecondaryLockScreenController";
+    private static final int REMOTE_CONTENT_READY_TIMEOUT_MILLIS = 500;
+    private final KeyguardUpdateMonitor mUpdateMonitor;
+    private final Context mContext;
+    private final ViewGroup mParent;
+    private AdminSecurityView mView;
+    private Handler mHandler;
+    private IKeyguardClient mClient;
+    private KeyguardSecurityCallback mKeyguardCallback;
+    private SurfaceControl.Transaction mTransaction;
+
+    private final ServiceConnection mConnection = new ServiceConnection() {
+        @Override
+        public void onServiceConnected(ComponentName className, IBinder service) {
+            mClient = IKeyguardClient.Stub.asInterface(service);
+            if (mView.isAttachedToWindow() && mClient != null) {
+                onSurfaceReady();
+
+                try {
+                    service.linkToDeath(mKeyguardClientDeathRecipient, 0);
+                } catch (RemoteException e) {
+                    // Failed to link to death, just dismiss and unbind the service for now.
+                    Log.e(TAG, "Lost connection to secondary lockscreen service", e);
+                    dismiss(KeyguardUpdateMonitor.getCurrentUser());
+                }
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName className) {
+            mClient = null;
+        }
+    };
+
+    private final IBinder.DeathRecipient mKeyguardClientDeathRecipient = () -> {
+        hide(); // hide also takes care of unlinking to death.
+        Log.d(TAG, "KeyguardClient service died");
+    };
+
+    private final IKeyguardCallback mCallback = new IKeyguardCallback.Stub() {
+        @Override
+        public void onDismiss() {
+            dismiss(UserHandle.getCallingUserId());
+        }
+
+        @Override
+        public void onSurfaceControlCreated(@Nullable SurfaceControl remoteSurfaceControl) {
+            if (mHandler != null) {
+                mHandler.removeCallbacksAndMessages(null);
+            }
+            if (remoteSurfaceControl != null) {
+                mTransaction.reparent(remoteSurfaceControl, mView.getSurfaceControl())
+                    .apply();
+            } else {
+                dismiss(KeyguardUpdateMonitor.getCurrentUser());
+            }
+        }
+    };
+
+    private final KeyguardUpdateMonitorCallback mUpdateCallback =
+            new KeyguardUpdateMonitorCallback() {
+                @Override
+                public void onSecondaryLockscreenRequirementChanged(int userId) {
+                    Intent newIntent = mUpdateMonitor.getSecondaryLockscreenRequirement(userId);
+                    if (newIntent == null) {
+                        dismiss(userId);
+                    }
+                }
+            };
+
+    @VisibleForTesting
+    protected SurfaceHolder.Callback mSurfaceHolderCallback = new SurfaceHolder.Callback() {
+        @Override
+        public void surfaceCreated(SurfaceHolder holder) {
+            final int userId = KeyguardUpdateMonitor.getCurrentUser();
+            mUpdateMonitor.registerCallback(mUpdateCallback);
+
+            if (mClient != null) {
+                onSurfaceReady();
+            }
+            mHandler.postDelayed(
+                    () -> {
+                        // If the remote content is not readied within the timeout period,
+                        // move on without the secondary lockscreen.
+                        dismiss(userId);
+                    },
+                    REMOTE_CONTENT_READY_TIMEOUT_MILLIS);
+        }
+
+        @Override
+        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
+
+        @Override
+        public void surfaceDestroyed(SurfaceHolder holder) {
+            mUpdateMonitor.removeCallback(mUpdateCallback);
+        }
+    };
+
+    public AdminSecondaryLockScreenController(Context context, ViewGroup parent,
+            KeyguardUpdateMonitor updateMonitor, KeyguardSecurityCallback callback,
+            Handler handler, SurfaceControl.Transaction transaction) {
+        mContext = context;
+        mHandler = handler;
+        mParent = parent;
+        mTransaction = transaction;
+        mUpdateMonitor = updateMonitor;
+        mKeyguardCallback = callback;
+        mView = new AdminSecurityView(mContext, mSurfaceHolderCallback);
+    }
+
+    /**
+     * Displays the Admin security Surface view.
+     */
+    public void show(Intent serviceIntent) {
+        mContext.bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE);
+        mParent.addView(mView);
+    }
+
+    /**
+     * Hides the Admin security Surface view.
+     */
+    public void hide() {
+        if (mView.isAttachedToWindow()) {
+            mParent.removeView(mView);
+        }
+        if (mClient != null) {
+            mClient.asBinder().unlinkToDeath(mKeyguardClientDeathRecipient, 0);
+            mContext.unbindService(mConnection);
+            mClient = null;
+        }
+    }
+
+    private void onSurfaceReady() {
+        try {
+            mClient.onSurfaceReady(mView.getInputToken(), mCallback);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error in onSurfaceReady", e);
+            dismiss(KeyguardUpdateMonitor.getCurrentUser());
+        }
+    }
+
+    private void dismiss(int userId) {
+        mHandler.removeCallbacksAndMessages(null);
+        if (mView != null && mView.isAttachedToWindow()
+                && userId == KeyguardUpdateMonitor.getCurrentUser()) {
+            hide();
+            mKeyguardCallback.dismiss(true, userId);
+        }
+    }
+
+    /**
+     * Custom {@link SurfaceView} used to allow a device admin to present an additional security
+     * screen.
+     */
+    private class AdminSecurityView extends SurfaceView {
+        private SurfaceHolder.Callback mSurfaceHolderCallback;
+
+        AdminSecurityView(Context context, SurfaceHolder.Callback surfaceHolderCallback) {
+            super(context);
+            mSurfaceHolderCallback = surfaceHolderCallback;
+            setZOrderOnTop(true);
+        }
+
+        @Override
+        protected void onAttachedToWindow() {
+            super.onAttachedToWindow();
+            getHolder().addCallback(mSurfaceHolderCallback);
+        }
+
+        @Override
+        protected void onDetachedFromWindow() {
+            super.onDetachedFromWindow();
+            getHolder().removeCallback(mSurfaceHolderCallback);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 9ae446e..ae78726 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -21,9 +21,12 @@
 import android.app.AlertDialog;
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
+import android.content.Intent;
 import android.content.res.ColorStateList;
 import android.graphics.Rect;
 import android.metrics.LogMaker;
+import android.os.Handler;
+import android.os.Looper;
 import android.os.UserHandle;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -31,6 +34,7 @@
 import android.util.TypedValue;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
+import android.view.SurfaceControl;
 import android.view.VelocityTracker;
 import android.view.View;
 import android.view.ViewConfiguration;
@@ -90,6 +94,7 @@
     private AlertDialog mAlertDialog;
     private InjectionInflationController mInjectionInflationController;
     private boolean mSwipeUpToRetry;
+    private AdminSecondaryLockScreenController mSecondaryLockScreenController;
 
     private final ViewConfiguration mViewConfiguration;
     private final SpringAnimation mSpringAnimation;
@@ -137,6 +142,9 @@
             SystemUIFactory.getInstance().getRootComponent());
         mViewConfiguration = ViewConfiguration.get(context);
         mKeyguardStateController = Dependency.get(KeyguardStateController.class);
+        mSecondaryLockScreenController = new AdminSecondaryLockScreenController(context, this,
+                mUpdateMonitor, mCallback, new Handler(Looper.myLooper()),
+                new SurfaceControl.Transaction());
     }
 
     public void setSecurityCallback(SecurityCallback callback) {
@@ -157,6 +165,7 @@
             mAlertDialog.dismiss();
             mAlertDialog = null;
         }
+        mSecondaryLockScreenController.hide();
         if (mCurrentSecuritySelection != SecurityMode.None) {
             getSecurityView(mCurrentSecuritySelection).onPause();
         }
@@ -532,6 +541,15 @@
                     break;
             }
         }
+        // Check for device admin specified additional security measures.
+        if (finish) {
+            Intent secondaryLockscreenIntent =
+                    mUpdateMonitor.getSecondaryLockscreenRequirement(targetUserId);
+            if (secondaryLockscreenIntent != null) {
+                mSecondaryLockScreenController.show(secondaryLockscreenIntent);
+                return false;
+            }
+        }
         if (eventSubtype != -1) {
             mMetricsLogger.write(new LogMaker(MetricsEvent.BOUNCER)
                     .setType(MetricsEvent.TYPE_DISMISS).setSubtype(eventSubtype));
@@ -751,6 +769,5 @@
     public void showUsabilityHint() {
         mSecurityViewFlipper.showUsabilityHint();
     }
-
 }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 65fc215..f03648a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -113,6 +113,7 @@
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Map.Entry;
 import java.util.TimeZone;
 import java.util.function.Consumer;
@@ -334,6 +335,7 @@
     private SparseBooleanArray mUserFingerprintAuthenticated = new SparseBooleanArray();
     private SparseBooleanArray mUserFaceAuthenticated = new SparseBooleanArray();
     private SparseBooleanArray mUserFaceUnlockRunning = new SparseBooleanArray();
+    private Map<Integer, Intent> mSecondaryLockscreenRequirement = new HashMap<Integer, Intent>();
 
     private static int sCurrentUser;
     private Runnable mUpdateBiometricListeningState = this::updateBiometricListeningState;
@@ -928,6 +930,45 @@
         return mUserTrustIsManaged.get(userId) && !isTrustDisabled(userId);
     }
 
+    private void updateSecondaryLockscreenRequirement(int userId) {
+        Intent oldIntent = mSecondaryLockscreenRequirement.get(userId);
+        boolean enabled = mDevicePolicyManager.isSecondaryLockscreenEnabled(userId);
+        boolean changed = false;
+
+        if (enabled && (oldIntent == null)) {
+            ResolveInfo resolveInfo =
+                    mContext.getPackageManager().resolveService(
+                            new Intent(
+                                    DevicePolicyManager.ACTION_BIND_SECONDARY_LOCKSCREEN_SERVICE),
+                            0);
+            if (resolveInfo != null) {
+                Intent newIntent = new Intent();
+                newIntent.setComponent(resolveInfo.serviceInfo.getComponentName());
+                mSecondaryLockscreenRequirement.put(userId, newIntent);
+                changed = true;
+            }
+        } else if (!enabled && (oldIntent != null)) {
+            mSecondaryLockscreenRequirement.put(userId, null);
+            changed = true;
+        }
+        if (changed) {
+            for (int i = 0; i < mCallbacks.size(); i++) {
+                KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+                if (cb != null) {
+                    cb.onSecondaryLockscreenRequirementChanged(userId);
+                }
+            }
+        }
+    }
+
+    /**
+     * Returns an Intent by which to bind to a service that will provide additional security screen
+     * content that must be shown prior to dismissing the keyguard for this user.
+     */
+    public Intent getSecondaryLockscreenRequirement(int userId) {
+        return mSecondaryLockscreenRequirement.get(userId);
+    }
+
     /**
      * Cached version of {@link TrustManager#isTrustUsuallyManaged(int)}.
      */
@@ -1113,7 +1154,8 @@
                         getSendingUserId()));
             } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
                     .equals(action)) {
-                mHandler.sendEmptyMessage(MSG_DPM_STATE_CHANGED);
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_DPM_STATE_CHANGED,
+                        getSendingUserId()));
             } else if (ACTION_USER_UNLOCKED.equals(action)) {
                 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_UNLOCKED,
                         getSendingUserId(), 0));
@@ -1530,7 +1572,7 @@
                         handleDeviceProvisioned();
                         break;
                     case MSG_DPM_STATE_CHANGED:
-                        handleDevicePolicyManagerStateChanged();
+                        handleDevicePolicyManagerStateChanged(msg.arg1);
                         break;
                     case MSG_USER_SWITCHING:
                         handleUserSwitching(msg.arg1, (IRemoteCallback) msg.obj);
@@ -1706,6 +1748,7 @@
         mUserIsUnlocked.put(user, mUserManager.isUserUnlocked(user));
         mDevicePolicyManager = context.getSystemService(DevicePolicyManager.class);
         mLogoutEnabled = mDevicePolicyManager.isLogoutEnabled();
+        updateSecondaryLockscreenRequirement(user);
         List<UserInfo> allUsers = mUserManager.getUsers();
         for (UserInfo userInfo : allUsers) {
             mUserTrustIsUsuallyManaged.put(userInfo.id,
@@ -2046,9 +2089,10 @@
     /**
      * Handle {@link #MSG_DPM_STATE_CHANGED}
      */
-    private void handleDevicePolicyManagerStateChanged() {
+    private void handleDevicePolicyManagerStateChanged(int userId) {
         checkIsHandlerThread();
         updateFingerprintListeningState();
+        updateSecondaryLockscreenRequirement(userId);
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 04502f0..8e87b7a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -310,4 +310,9 @@
      */
     public void onBiometricsCleared() { }
 
+    /**
+     * Called when the secondary lock screen requirement changes.
+     */
+    public void onSecondaryLockscreenRequirementChanged(int userId) { }
+
 }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
index 7b4816f..044c5a0 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
@@ -28,7 +28,6 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
-import android.os.UserManager;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -381,16 +380,7 @@
                     0 /* animateDurationMs */);
             mSize = newSize;
         } else if (newSize == AuthDialog.SIZE_LARGE) {
-            final boolean isManagedProfile = Utils.isManagedProfile(mContext, mUserId);
-
-            // If it's a managed profile, animate the contents and panel down, since the credential
-            // contents will be shown on the same "layer" as the background. If it's not a managed
-            // profile, animate the contents up and expand the panel to full-screen - the credential
-            // contents will be shown on the same "layer" as the panel.
-            final float translationY = isManagedProfile ?
-                    -getResources().getDimension(
-                            R.dimen.biometric_dialog_animation_translation_offset)
-                    : getResources().getDimension(
+            final float translationY = getResources().getDimension(
                             R.dimen.biometric_dialog_medium_to_large_translation_offset);
             final AuthBiometricView biometricView = this;
 
@@ -421,26 +411,20 @@
                 biometricView.setAlpha(opacity);
             });
 
-            if (!isManagedProfile) {
-                mPanelController.setUseFullScreen(true);
-                mPanelController.updateForContentDimensions(
-                        mPanelController.getContainerWidth(),
-                        mPanelController.getContainerHeight(),
-                        mInjector.getMediumToLargeAnimationDurationMs());
-            }
+            mPanelController.setUseFullScreen(true);
+            mPanelController.updateForContentDimensions(
+                    mPanelController.getContainerWidth(),
+                    mPanelController.getContainerHeight(),
+                    mInjector.getMediumToLargeAnimationDurationMs());
 
             // Start the animations together
             AnimatorSet as = new AnimatorSet();
             List<Animator> animators = new ArrayList<>();
             animators.add(translationAnimator);
             animators.add(opacityAnimator);
-            if (isManagedProfile) {
-                animators.add(mPanelController.getTranslationAnimator(translationY));
-                animators.add(mPanelController.getAlphaAnimator(0));
-            }
+
             as.playTogether(animators);
-            as.setDuration(isManagedProfile ? mInjector.getMediumToLargeAnimationDurationMs()
-                    : mInjector.getMediumToLargeAnimationDurationMs() * 2 / 3);
+            as.setDuration(mInjector.getMediumToLargeAnimationDurationMs() * 2 / 3);
             as.start();
         } else {
             Log.e(TAG, "Unknown transition from: " + mSize + " to: " + newSize);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index 4312a52..89446ad 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -19,11 +19,8 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.graphics.PixelFormat;
-import android.graphics.PorterDuff;
-import android.graphics.drawable.Drawable;
 import android.hardware.biometrics.BiometricAuthenticator;
 import android.os.Binder;
 import android.os.Bundle;
@@ -168,9 +165,8 @@
                     R.layout.auth_container_view, root, false /* attachToRoot */);
         }
 
-        AuthPanelController getPanelController(Context context, View panelView,
-                boolean isManagedProfile) {
-            return new AuthPanelController(context, panelView, isManagedProfile);
+        AuthPanelController getPanelController(Context context, View panelView) {
+            return new AuthPanelController(context, panelView);
         }
 
         ImageView getBackgroundView(FrameLayout parent) {
@@ -256,10 +252,8 @@
         final LayoutInflater factory = LayoutInflater.from(mContext);
         mFrameLayout = mInjector.inflateContainerView(factory, this);
 
-        final boolean isManagedProfile = Utils.isManagedProfile(mContext, mConfig.mUserId);
-
         mPanelView = mInjector.getPanelView(mFrameLayout);
-        mPanelController = mInjector.getPanelController(mContext, mPanelView, isManagedProfile);
+        mPanelController = mInjector.getPanelController(mContext, mPanelView);
 
         // Inflate biometric view only if necessary.
         if (Utils.isBiometricAllowed(mConfig.mBiometricPromptBundle)) {
@@ -281,16 +275,6 @@
         mBiometricScrollView = mInjector.getBiometricScrollView(mFrameLayout);
         mBackgroundView = mInjector.getBackgroundView(mFrameLayout);
 
-        if (isManagedProfile) {
-            final Drawable image = getResources().getDrawable(R.drawable.work_challenge_background,
-                    mContext.getTheme());
-            final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
-            image.setColorFilter(dpm.getOrganizationColorForUser(mConfig.mUserId),
-                    PorterDuff.Mode.DARKEN);
-            mBackgroundView.setScaleType(ImageView.ScaleType.CENTER_CROP);
-            mBackgroundView.setImageDrawable(image);
-        }
-
         addView(mFrameLayout);
 
         setOnKeyListener((v, keyCode, event) -> {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthPanelController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthPanelController.java
index 4acbade..11503fb 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthPanelController.java
@@ -37,7 +37,6 @@
 
     private final Context mContext;
     private final View mPanelView;
-    private final boolean mIsManagedProfile;
 
     private boolean mUseFullScreen;
 
@@ -115,13 +114,6 @@
         final float cornerRadius = mUseFullScreen ? 0 : mContext.getResources()
                 .getDimension(R.dimen.biometric_dialog_corner_size);
 
-        // When going to full-screen for managed profiles, fade away so the managed profile
-        // background behind this view becomes visible.
-        final boolean shouldFadeAway = mUseFullScreen && mIsManagedProfile;
-        final int alpha = shouldFadeAway ? 0 : 255;
-        final float elevation = shouldFadeAway ? 0 :
-                mContext.getResources().getDimension(R.dimen.biometric_dialog_elevation);
-
         if (animateDurationMs > 0) {
             // Animate margin
             ValueAnimator marginAnimator = ValueAnimator.ofInt(mMargin, margin);
@@ -148,21 +140,11 @@
                 mContentWidth = (int) animation.getAnimatedValue();
             });
 
-            // Animate background
-            ValueAnimator alphaAnimator = ValueAnimator.ofInt(
-                    mPanelView.getBackground().getAlpha(), alpha);
-            alphaAnimator.addUpdateListener((animation) -> {
-                if (shouldFadeAway) {
-                    mPanelView.getBackground().setAlpha((int) animation.getAnimatedValue());
-                }
-            });
-
             // Play together
             AnimatorSet as = new AnimatorSet();
             as.setDuration(animateDurationMs);
             as.setInterpolator(new AccelerateDecelerateInterpolator());
-            as.playTogether(cornerAnimator, heightAnimator, widthAnimator, marginAnimator,
-                    alphaAnimator);
+            as.playTogether(cornerAnimator, heightAnimator, widthAnimator, marginAnimator);
             as.start();
 
         } else {
@@ -170,7 +152,6 @@
             mCornerRadius = cornerRadius;
             mContentWidth = contentWidth;
             mContentHeight = contentHeight;
-            mPanelView.getBackground().setAlpha(alpha);
             mPanelView.invalidateOutline();
         }
     }
@@ -183,10 +164,9 @@
         return mContainerHeight;
     }
 
-    AuthPanelController(Context context, View panelView, boolean isManagedProfile) {
+    AuthPanelController(Context context, View panelView) {
         mContext = context;
         mPanelView = panelView;
-        mIsManagedProfile = isManagedProfile;
         mCornerRadius = context.getResources()
                 .getDimension(R.dimen.biometric_dialog_corner_size);
         mMargin = (int) context.getResources()
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
index ccbbb24..cc0824e 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
@@ -218,7 +218,7 @@
         }
         mPendingBubbles.remove(bubble); // No longer pending once we're here
         Bubble prevBubble = getBubbleWithKey(bubble.getKey());
-        suppressFlyout |= !shouldShowFlyout(bubble.getEntry());
+        suppressFlyout |= !bubble.getEntry().getRanking().visuallyInterruptive();
 
         if (prevBubble == null) {
             // Create a new bubble
@@ -329,14 +329,6 @@
         return bubbleChildren;
     }
 
-    private boolean shouldShowFlyout(NotificationEntry notif) {
-        if (notif.getRanking().visuallyInterruptive()) {
-            return true;
-        }
-        return hasBubbleWithKey(notif.getKey())
-                && !getBubbleWithKey(notif.getKey()).showInShade();
-    }
-
     private void doAdd(Bubble bubble) {
         if (DEBUG_BUBBLE_DATA) {
             Log.d(TAG, "doAdd: " + bubble);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java
new file mode 100644
index 0000000..1954b39
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java
@@ -0,0 +1,207 @@
+/*
+ * 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.keyguard;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.AdditionalAnswers.answerVoid;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.admin.IKeyguardCallback;
+import android.app.admin.IKeyguardClient;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.testing.TestableLooper.RunWithLooper;
+import android.testing.ViewUtils;
+import android.view.SurfaceControl;
+import android.view.SurfaceView;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+
+@RunWithLooper
+@RunWith(AndroidTestingRunner.class)
+@SmallTest
+public class AdminSecondaryLockScreenControllerTest extends SysuiTestCase {
+
+    private static final int TARGET_USER_ID = KeyguardUpdateMonitor.getCurrentUser();
+
+    private AdminSecondaryLockScreenController mTestController;
+    private ComponentName mComponentName;
+    private Intent mServiceIntent;
+    private TestableLooper mTestableLooper;
+    private ViewGroup mParent;
+
+    @Mock
+    private Handler mHandler;
+    @Mock
+    private IKeyguardClient.Stub mKeyguardClient;
+    @Mock
+    private KeyguardSecurityCallback mKeyguardCallback;
+    @Mock
+    private KeyguardUpdateMonitor mUpdateMonitor;
+    @Spy
+    private StubTransaction mTransaction;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mParent = spy(new FrameLayout(mContext));
+        ViewUtils.attachView(mParent);
+
+        mTestableLooper = TestableLooper.get(this);
+        mComponentName = new ComponentName(mContext, "FakeKeyguardClient.class");
+        mServiceIntent = new Intent().setComponent(mComponentName);
+
+        mContext.addMockService(mComponentName, mKeyguardClient);
+        // Have Stub.asInterface return the mocked interface.
+        when(mKeyguardClient.queryLocalInterface(anyString())).thenReturn(mKeyguardClient);
+        when(mKeyguardClient.asBinder()).thenReturn(mKeyguardClient);
+
+        mTestController = new AdminSecondaryLockScreenController(
+                mContext, mParent, mUpdateMonitor, mKeyguardCallback, mHandler, mTransaction);
+    }
+
+    @Test
+    public void testShow() throws Exception {
+        doAnswer(invocation -> {
+            IKeyguardCallback callback = (IKeyguardCallback) invocation.getArguments()[1];
+            callback.onSurfaceControlCreated(new SurfaceControl());
+            return null;
+        }).when(mKeyguardClient).onSurfaceReady(any(), any(IKeyguardCallback.class));
+
+        mTestController.show(mServiceIntent);
+
+        verifySurfaceReady();
+        verify(mTransaction).reparent(any(), any());
+        assertThat(mContext.isBound(mComponentName)).isTrue();
+    }
+
+    @Test
+    public void testShow_dismissedByCallback() throws Exception {
+        doAnswer(invocation -> {
+            IKeyguardCallback callback = (IKeyguardCallback) invocation.getArguments()[1];
+            callback.onDismiss();
+            return null;
+        }).when(mKeyguardClient).onSurfaceReady(any(), any(IKeyguardCallback.class));
+
+        mTestController.show(mServiceIntent);
+
+        verifyViewDismissed(verifySurfaceReady());
+    }
+
+    @Test
+    public void testHide() throws Exception {
+        // Show the view first, then hide.
+        doAnswer(invocation -> {
+            IKeyguardCallback callback = (IKeyguardCallback) invocation.getArguments()[1];
+            callback.onSurfaceControlCreated(new SurfaceControl());
+            return null;
+        }).when(mKeyguardClient).onSurfaceReady(any(), any(IKeyguardCallback.class));
+
+        mTestController.show(mServiceIntent);
+        SurfaceView v = verifySurfaceReady();
+
+        mTestController.hide();
+        verify(mParent).removeView(v);
+        assertThat(mContext.isBound(mComponentName)).isFalse();
+    }
+
+    @Test
+    public void testHide_notShown() throws Exception {
+        mTestController.hide();
+        // Nothing should happen if trying to hide when the view isn't attached yet.
+        verify(mParent, never()).removeView(any(SurfaceView.class));
+    }
+
+    @Test
+    public void testDismissed_onSurfaceReady_RemoteException() throws Exception {
+        doThrow(new RemoteException()).when(mKeyguardClient)
+                .onSurfaceReady(any(), any(IKeyguardCallback.class));
+
+        mTestController.show(mServiceIntent);
+
+        verifyViewDismissed(verifySurfaceReady());
+    }
+
+    @Test
+    public void testDismissed_onSurfaceReady_timeout() throws Exception {
+        // Mocked KeyguardClient never handles the onSurfaceReady, so the operation times out,
+        // resulting in the view being dismissed.
+        doAnswer(answerVoid(Runnable::run)).when(mHandler)
+                .postDelayed(any(Runnable.class), anyLong());
+
+        mTestController.show(mServiceIntent);
+
+        verifyViewDismissed(verifySurfaceReady());
+    }
+
+    private SurfaceView verifySurfaceReady() throws Exception {
+        mTestableLooper.processAllMessages();
+        ArgumentCaptor<SurfaceView> captor = ArgumentCaptor.forClass(SurfaceView.class);
+        verify(mParent).addView(captor.capture());
+
+        mTestableLooper.processAllMessages();
+        verify(mKeyguardClient).onSurfaceReady(any(), any(IKeyguardCallback.class));
+        return captor.getValue();
+    }
+
+    private void verifyViewDismissed(SurfaceView v) throws Exception {
+        verify(mParent).removeView(v);
+        verify(mKeyguardCallback).dismiss(true, TARGET_USER_ID);
+        assertThat(mContext.isBound(mComponentName)).isFalse();
+    }
+
+    /**
+     * Stubbed {@link SurfaceControl.Transaction} class that can be used when unit testing to
+     * avoid calls to native code.
+     */
+    private class StubTransaction extends SurfaceControl.Transaction {
+        @Override
+        public void apply() {
+        }
+
+        @Override
+        public SurfaceControl.Transaction reparent(SurfaceControl sc, SurfaceControl newParent) {
+            return this;
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 12da006..b3c2ba3 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -34,12 +34,16 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.Activity;
 import android.app.admin.DevicePolicyManager;
 import android.app.trust.TrustManager;
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
 import android.hardware.biometrics.BiometricManager;
 import android.hardware.biometrics.BiometricSourceType;
 import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
@@ -519,6 +523,52 @@
         assertThat(mKeyguardUpdateMonitor.isTrustUsuallyManaged(user)).isFalse();
     }
 
+    @Test
+    public void testSecondaryLockscreenRequirement() {
+        int user = KeyguardUpdateMonitor.getCurrentUser();
+        String packageName = "fake.test.package";
+        String cls = "FakeService";
+        ServiceInfo serviceInfo = new ServiceInfo();
+        serviceInfo.packageName = packageName;
+        serviceInfo.name = cls;
+        ResolveInfo resolveInfo = new ResolveInfo();
+        resolveInfo.serviceInfo = serviceInfo;
+        when(mPackageManager.resolveService(any(Intent.class), eq(0))).thenReturn(resolveInfo);
+        when(mDevicePolicyManager.isSecondaryLockscreenEnabled(eq(user))).thenReturn(true, false);
+
+        // Initially null.
+        assertThat(mKeyguardUpdateMonitor.getSecondaryLockscreenRequirement(user)).isNull();
+
+        // Set non-null after DPM change.
+        setBroadcastReceiverPendingResult(mKeyguardUpdateMonitor.mBroadcastAllReceiver);
+        Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
+        mKeyguardUpdateMonitor.mBroadcastAllReceiver.onReceive(getContext(), intent);
+        mTestableLooper.processAllMessages();
+
+        Intent storedIntent = mKeyguardUpdateMonitor.getSecondaryLockscreenRequirement(user);
+        assertThat(storedIntent.getComponent().getClassName()).isEqualTo(cls);
+        assertThat(storedIntent.getComponent().getPackageName()).isEqualTo(packageName);
+
+        // Back to null after another DPM change.
+        mKeyguardUpdateMonitor.mBroadcastAllReceiver.onReceive(getContext(), intent);
+        mTestableLooper.processAllMessages();
+        assertThat(mKeyguardUpdateMonitor.getSecondaryLockscreenRequirement(user)).isNull();
+    }
+
+    private void setBroadcastReceiverPendingResult(BroadcastReceiver receiver) {
+        BroadcastReceiver.PendingResult pendingResult =
+                new BroadcastReceiver.PendingResult(Activity.RESULT_OK,
+                        "resultData",
+                        /* resultExtras= */ null,
+                        BroadcastReceiver.PendingResult.TYPE_UNREGISTERED,
+                        /* ordered= */ true,
+                        /* sticky= */ false,
+                        /* token= */ null,
+                        UserHandle.myUserId(),
+                        /* flags= */ 0);
+        receiver.setPendingResult(pendingResult);
+    }
+
     private Intent putPhoneInfo(Intent intent, Bundle data, Boolean simInited) {
         int subscription = simInited
                 ? 1/* mock subid=1 */ : SubscriptionManager.DUMMY_SUBSCRIPTION_ID_BASE;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java
index 25bcb54..f264259 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java
@@ -211,8 +211,7 @@
         }
 
         @Override
-        public AuthPanelController getPanelController(Context context, View view,
-                boolean isManagedProfile) {
+        public AuthPanelController getPanelController(Context context, View view) {
             return mock(AuthPanelController.class);
         }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
index 7daf922..b09603d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
@@ -228,7 +228,7 @@
     }
 
     @Test
-    public void sameUpdate_NotInShade_showFlyout() {
+    public void sameUpdate_NotInShade_NotVisuallyInterruptive_dontShowFlyout() {
         // Setup
         mBubbleData.setListener(mListener);
 
@@ -247,7 +247,7 @@
 
         // Verify
         BubbleData.Update update = mUpdateCaptor.getValue();
-        assertThat(update.updatedBubble.showFlyout()).isTrue();
+        assertThat(update.updatedBubble.showFlyout()).isFalse();
     }
 
     // COLLAPSED / ADD
diff --git a/proto/Android.bp b/proto/Android.bp
index 7cf6ce7..01a72ea 100644
--- a/proto/Android.bp
+++ b/proto/Android.bp
@@ -32,3 +32,8 @@
     name: "system-messages-proto-src",
     srcs: ["src/system_messages.proto"],
 }
+
+filegroup {
+    name: "ipconnectivity-proto-src",
+    srcs: ["src/ipconnectivity.proto"],
+}
diff --git a/services/core/java/com/android/server/BluetoothAirplaneModeListener.java b/services/core/java/com/android/server/BluetoothAirplaneModeListener.java
new file mode 100644
index 0000000..31cd5d5
--- /dev/null
+++ b/services/core/java/com/android/server/BluetoothAirplaneModeListener.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2019 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.server;
+
+import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothProfile.ServiceListener;
+import android.content.Context;
+import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.provider.Settings;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * The BluetoothAirplaneModeListener handles system airplane mode change callback and checks
+ * whether we need to inform BluetoothManagerService on this change.
+ *
+ * The information of airplane mode turns on would not be passed to the BluetoothManagerService
+ * when Bluetooth is on and Bluetooth is in one of the following situations:
+ *   1. Bluetooth A2DP is connected.
+ *   2. Bluetooth Hearing Aid profile is connected.
+ */
+class BluetoothAirplaneModeListener {
+    private static final String TAG = "BluetoothAirplaneModeListener";
+    @VisibleForTesting static final String TOAST_COUNT = "bluetooth_airplane_toast_count";
+
+    private static final int MSG_AIRPLANE_MODE_CHANGED = 0;
+
+    @VisibleForTesting static final int MAX_TOAST_COUNT = 10; // 10 times
+
+    private final BluetoothManagerService mBluetoothManager;
+    private final BluetoothAirplaneModeHandler mHandler;
+    private AirplaneModeHelper mAirplaneHelper;
+
+    @VisibleForTesting int mToastCount = 0;
+
+    BluetoothAirplaneModeListener(BluetoothManagerService service, Looper looper, Context context) {
+        mBluetoothManager = service;
+
+        mHandler = new BluetoothAirplaneModeHandler(looper);
+        context.getContentResolver().registerContentObserver(
+                Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true,
+                mAirplaneModeObserver);
+    }
+
+    private final ContentObserver mAirplaneModeObserver = new ContentObserver(null) {
+        @Override
+        public void onChange(boolean unused) {
+            // Post from system main thread to android_io thread.
+            Message msg = mHandler.obtainMessage(MSG_AIRPLANE_MODE_CHANGED);
+            mHandler.sendMessage(msg);
+        }
+    };
+
+    private class BluetoothAirplaneModeHandler extends Handler {
+        BluetoothAirplaneModeHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_AIRPLANE_MODE_CHANGED:
+                    handleAirplaneModeChange();
+                    break;
+                default:
+                    Log.e(TAG, "Invalid message: " + msg.what);
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Call after boot complete
+     */
+    @VisibleForTesting
+    void start(AirplaneModeHelper helper) {
+        Log.i(TAG, "start");
+        mAirplaneHelper = helper;
+        mToastCount = mAirplaneHelper.getSettingsInt(TOAST_COUNT);
+    }
+
+    @VisibleForTesting
+    boolean shouldPopToast() {
+        if (mToastCount >= MAX_TOAST_COUNT) {
+            return false;
+        }
+        mToastCount++;
+        mAirplaneHelper.setSettingsInt(TOAST_COUNT, mToastCount);
+        return true;
+    }
+
+    @VisibleForTesting
+    void handleAirplaneModeChange() {
+        if (shouldSkipAirplaneModeChange()) {
+            Log.i(TAG, "Ignore airplane mode change");
+            // We have to store Bluetooth state here, so if user turns off Bluetooth
+            // after airplane mode is turned on, we don't forget to turn on Bluetooth
+            // when airplane mode turns off.
+            mAirplaneHelper.setSettingsInt(Settings.Global.BLUETOOTH_ON,
+                    BluetoothManagerService.BLUETOOTH_ON_AIRPLANE);
+            if (shouldPopToast()) {
+                mAirplaneHelper.showToastMessage();
+            }
+            return;
+        }
+        mAirplaneHelper.onAirplaneModeChanged(mBluetoothManager);
+    }
+
+    @VisibleForTesting
+    boolean shouldSkipAirplaneModeChange() {
+        if (mAirplaneHelper == null) {
+            return false;
+        }
+        if (!mAirplaneHelper.isBluetoothOn() || !mAirplaneHelper.isAirplaneModeOn()
+                || !mAirplaneHelper.isA2dpOrHearingAidConnected()) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Helper class that handles callout and callback methods without
+     * complex logic.
+     */
+    @VisibleForTesting
+    public static class AirplaneModeHelper {
+        private volatile BluetoothA2dp mA2dp;
+        private volatile BluetoothHearingAid mHearingAid;
+        private final BluetoothAdapter mAdapter;
+        private final Context mContext;
+
+        AirplaneModeHelper(Context context) {
+            mAdapter = BluetoothAdapter.getDefaultAdapter();
+            mContext = context;
+
+            mAdapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.A2DP);
+            mAdapter.getProfileProxy(mContext, mProfileServiceListener,
+                    BluetoothProfile.HEARING_AID);
+        }
+
+        private final ServiceListener mProfileServiceListener = new ServiceListener() {
+            @Override
+            public void onServiceConnected(int profile, BluetoothProfile proxy) {
+                // Setup Bluetooth profile proxies
+                switch (profile) {
+                    case BluetoothProfile.A2DP:
+                        mA2dp = (BluetoothA2dp) proxy;
+                        break;
+                    case BluetoothProfile.HEARING_AID:
+                        mHearingAid = (BluetoothHearingAid) proxy;
+                        break;
+                    default:
+                        break;
+                }
+            }
+
+            @Override
+            public void onServiceDisconnected(int profile) {
+                // Clear Bluetooth profile proxies
+                switch (profile) {
+                    case BluetoothProfile.A2DP:
+                        mA2dp = null;
+                        break;
+                    case BluetoothProfile.HEARING_AID:
+                        mHearingAid = null;
+                        break;
+                    default:
+                        break;
+                }
+            }
+        };
+
+        @VisibleForTesting
+        public boolean isA2dpOrHearingAidConnected() {
+            return isA2dpConnected() || isHearingAidConnected();
+        }
+
+        @VisibleForTesting
+        public boolean isBluetoothOn() {
+            final BluetoothAdapter adapter = mAdapter;
+            if (adapter == null) {
+                return false;
+            }
+            return adapter.getLeState() == BluetoothAdapter.STATE_ON;
+        }
+
+        @VisibleForTesting
+        public boolean isAirplaneModeOn() {
+            return Settings.Global.getInt(mContext.getContentResolver(),
+                    Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
+        }
+
+        @VisibleForTesting
+        public void onAirplaneModeChanged(BluetoothManagerService managerService) {
+            managerService.onAirplaneModeChanged();
+        }
+
+        @VisibleForTesting
+        public int getSettingsInt(String name) {
+            return Settings.Global.getInt(mContext.getContentResolver(),
+                    name, 0);
+        }
+
+        @VisibleForTesting
+        public void setSettingsInt(String name, int value) {
+            Settings.Global.putInt(mContext.getContentResolver(),
+                    name, value);
+        }
+
+        @VisibleForTesting
+        public void showToastMessage() {
+            Resources r = mContext.getResources();
+            final CharSequence text = r.getString(
+                    R.string.bluetooth_airplane_mode_toast, 0);
+            Toast.makeText(mContext, text, Toast.LENGTH_LONG).show();
+        }
+
+        private boolean isA2dpConnected() {
+            final BluetoothA2dp a2dp = mA2dp;
+            if (a2dp == null) {
+                return false;
+            }
+            return a2dp.getConnectedDevices().size() > 0;
+        }
+
+        private boolean isHearingAidConnected() {
+            final BluetoothHearingAid hearingAid = mHearingAid;
+            if (hearingAid == null) {
+                return false;
+            }
+            return hearingAid.getConnectedDevices().size() > 0;
+        }
+    };
+}
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 470300e..3774b64 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -72,6 +72,7 @@
 import android.util.StatsLog;
 
 import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.DumpUtils;
 import com.android.server.pm.UserRestrictionsUtils;
 
@@ -143,7 +144,8 @@
     // Bluetooth persisted setting is on
     // but Airplane mode will affect Bluetooth state at start up
     // and Airplane mode will have higher priority.
-    private static final int BLUETOOTH_ON_AIRPLANE = 2;
+    @VisibleForTesting
+    static final int BLUETOOTH_ON_AIRPLANE = 2;
 
     private static final int SERVICE_IBLUETOOTH = 1;
     private static final int SERVICE_IBLUETOOTHGATT = 2;
@@ -164,6 +166,8 @@
     private boolean mBinding;
     private boolean mUnbinding;
 
+    private BluetoothAirplaneModeListener mBluetoothAirplaneModeListener;
+
     // used inside handler thread
     private boolean mQuietEnable = false;
     private boolean mEnable;
@@ -262,68 +266,65 @@
                 }
             };
 
-    private final ContentObserver mAirplaneModeObserver = new ContentObserver(null) {
-        @Override
-        public void onChange(boolean unused) {
-            synchronized (this) {
-                if (isBluetoothPersistedStateOn()) {
-                    if (isAirplaneModeOn()) {
-                        persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE);
-                    } else {
-                        persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
-                    }
-                }
-
-                int st = BluetoothAdapter.STATE_OFF;
-                try {
-                    mBluetoothLock.readLock().lock();
-                    if (mBluetooth != null) {
-                        st = mBluetooth.getState();
-                    }
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Unable to call getState", e);
-                    return;
-                } finally {
-                    mBluetoothLock.readLock().unlock();
-                }
-
-                Slog.d(TAG,
-                        "Airplane Mode change - current state:  " + BluetoothAdapter.nameForState(
-                                st) + ", isAirplaneModeOn()=" + isAirplaneModeOn());
-
+    public void onAirplaneModeChanged() {
+        synchronized (this) {
+            if (isBluetoothPersistedStateOn()) {
                 if (isAirplaneModeOn()) {
-                    // Clear registered LE apps to force shut-off
-                    clearBleApps();
-
-                    // If state is BLE_ON make sure we trigger disableBLE
-                    if (st == BluetoothAdapter.STATE_BLE_ON) {
-                        try {
-                            mBluetoothLock.readLock().lock();
-                            if (mBluetooth != null) {
-                                addActiveLog(
-                                        BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
-                                        mContext.getPackageName(), false);
-                                mBluetooth.onBrEdrDown();
-                                mEnable = false;
-                                mEnableExternal = false;
-                            }
-                        } catch (RemoteException e) {
-                            Slog.e(TAG, "Unable to call onBrEdrDown", e);
-                        } finally {
-                            mBluetoothLock.readLock().unlock();
-                        }
-                    } else if (st == BluetoothAdapter.STATE_ON) {
-                        sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
-                                mContext.getPackageName());
-                    }
-                } else if (mEnableExternal) {
-                    sendEnableMsg(mQuietEnableExternal,
-                            BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
-                            mContext.getPackageName());
+                    persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE);
+                } else {
+                    persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
                 }
             }
+
+            int st = BluetoothAdapter.STATE_OFF;
+            try {
+                mBluetoothLock.readLock().lock();
+                if (mBluetooth != null) {
+                    st = mBluetooth.getState();
+                }
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Unable to call getState", e);
+                return;
+            } finally {
+                mBluetoothLock.readLock().unlock();
+            }
+
+            Slog.d(TAG,
+                    "Airplane Mode change - current state:  " + BluetoothAdapter.nameForState(
+                            st) + ", isAirplaneModeOn()=" + isAirplaneModeOn());
+
+            if (isAirplaneModeOn()) {
+                // Clear registered LE apps to force shut-off
+                clearBleApps();
+
+                // If state is BLE_ON make sure we trigger disableBLE
+                if (st == BluetoothAdapter.STATE_BLE_ON) {
+                    try {
+                        mBluetoothLock.readLock().lock();
+                        if (mBluetooth != null) {
+                            addActiveLog(
+                                    BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
+                                    mContext.getPackageName(), false);
+                            mBluetooth.onBrEdrDown();
+                            mEnable = false;
+                            mEnableExternal = false;
+                        }
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "Unable to call onBrEdrDown", e);
+                    } finally {
+                        mBluetoothLock.readLock().unlock();
+                    }
+                } else if (st == BluetoothAdapter.STATE_ON) {
+                    sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
+                            mContext.getPackageName());
+                }
+            } else if (mEnableExternal) {
+                sendEnableMsg(mQuietEnableExternal,
+                        BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
+                        mContext.getPackageName());
+            }
         }
-    };
+    }
 
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
@@ -435,9 +436,8 @@
                 Settings.Global.getString(mContentResolver, Settings.Global.AIRPLANE_MODE_RADIOS);
         if (airplaneModeRadios == null || airplaneModeRadios.contains(
                 Settings.Global.RADIO_BLUETOOTH)) {
-            mContentResolver.registerContentObserver(
-                    Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true,
-                    mAirplaneModeObserver);
+            mBluetoothAirplaneModeListener = new BluetoothAirplaneModeListener(
+                    this, IoThread.get().getLooper(), context);
         }
 
         int systemUiUid = -1;
@@ -483,6 +483,17 @@
         return state != BLUETOOTH_OFF;
     }
 
+    private boolean isBluetoothPersistedStateOnAirplane() {
+        if (!supportBluetoothPersistedState()) {
+            return false;
+        }
+        int state = Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON, -1);
+        if (DBG) {
+            Slog.d(TAG, "Bluetooth persisted state: " + state);
+        }
+        return state == BLUETOOTH_ON_AIRPLANE;
+    }
+
     /**
      *  Returns true if the Bluetooth saved state is BLUETOOTH_ON_BLUETOOTH
      */
@@ -988,10 +999,12 @@
         }
 
         synchronized (mReceiver) {
-            if (persist) {
-                persistBluetoothSetting(BLUETOOTH_OFF);
+            if (!isBluetoothPersistedStateOnAirplane()) {
+                if (persist) {
+                    persistBluetoothSetting(BLUETOOTH_OFF);
+                }
+                mEnableExternal = false;
             }
-            mEnableExternal = false;
             sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST,
                     packageName);
         }
@@ -1219,6 +1232,10 @@
             Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
             mHandler.sendMessage(getMsg);
         }
+        if (mBluetoothAirplaneModeListener != null) {
+            mBluetoothAirplaneModeListener.start(
+                    new BluetoothAirplaneModeListener.AirplaneModeHelper(mContext));
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 7ab3453..1c9f5dc 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1571,48 +1571,49 @@
         enforceAccessPermission();
         final int uid = Binder.getCallingUid();
         NetworkState state = getUnfilteredActiveNetworkState(uid);
-        return state.linkProperties;
+        if (state.linkProperties == null) return null;
+        return linkPropertiesRestrictedForCallerPermissions(state.linkProperties,
+                Binder.getCallingPid(), uid);
     }
 
     @Override
     public LinkProperties getLinkPropertiesForType(int networkType) {
         enforceAccessPermission();
         NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
-        if (nai != null) {
-            synchronized (nai) {
-                return new LinkProperties(nai.linkProperties);
-            }
-        }
-        return null;
+        final LinkProperties lp = getLinkProperties(nai);
+        if (lp == null) return null;
+        return linkPropertiesRestrictedForCallerPermissions(
+                lp, Binder.getCallingPid(), Binder.getCallingUid());
     }
 
     // TODO - this should be ALL networks
     @Override
     public LinkProperties getLinkProperties(Network network) {
         enforceAccessPermission();
-        return getLinkProperties(getNetworkAgentInfoForNetwork(network));
+        final LinkProperties lp = getLinkProperties(getNetworkAgentInfoForNetwork(network));
+        if (lp == null) return null;
+        return linkPropertiesRestrictedForCallerPermissions(
+                lp, Binder.getCallingPid(), Binder.getCallingUid());
     }
 
-    private LinkProperties getLinkProperties(NetworkAgentInfo nai) {
+    @Nullable
+    private LinkProperties getLinkProperties(@Nullable NetworkAgentInfo nai) {
         if (nai == null) {
             return null;
         }
         synchronized (nai) {
-            return new LinkProperties(nai.linkProperties);
+            return nai.linkProperties;
         }
     }
 
     private NetworkCapabilities getNetworkCapabilitiesInternal(NetworkAgentInfo nai) {
-        if (nai != null) {
-            synchronized (nai) {
-                if (nai.networkCapabilities != null) {
-                    return networkCapabilitiesRestrictedForCallerPermissions(
-                            nai.networkCapabilities,
-                            Binder.getCallingPid(), Binder.getCallingUid());
-                }
-            }
+        if (nai == null) return null;
+        synchronized (nai) {
+            if (nai.networkCapabilities == null) return null;
+            return networkCapabilitiesRestrictedForCallerPermissions(
+                    nai.networkCapabilities,
+                    Binder.getCallingPid(), Binder.getCallingUid());
         }
-        return null;
     }
 
     @Override
@@ -1634,6 +1635,29 @@
         return newNc;
     }
 
+    private LinkProperties linkPropertiesRestrictedForCallerPermissions(
+            LinkProperties lp, int callerPid, int callerUid) {
+        if (lp == null) return new LinkProperties();
+
+        // Only do a permission check if sanitization is needed, to avoid unnecessary binder calls.
+        final boolean needsSanitization =
+                (lp.getCaptivePortalApiUrl() != null || lp.getCaptivePortalData() != null);
+        if (!needsSanitization) {
+            return new LinkProperties(lp);
+        }
+
+        if (checkSettingsPermission(callerPid, callerUid)) {
+            return lp.makeSensitiveFieldsParcelingCopy();
+        }
+
+        final LinkProperties newLp = new LinkProperties(lp);
+        // Sensitive fields would not be parceled anyway, but sanitize for consistency before the
+        // object gets parceled.
+        newLp.setCaptivePortalApiUrl(null);
+        newLp.setCaptivePortalData(null);
+        return newLp;
+    }
+
     private void restrictRequestUidsForCaller(NetworkCapabilities nc) {
         if (!checkSettingsPermission()) {
             nc.setSingleUid(Binder.getCallingUid());
@@ -6145,7 +6169,8 @@
             case ConnectivityManager.CALLBACK_AVAILABLE: {
                 putParcelable(bundle, networkCapabilitiesRestrictedForCallerPermissions(
                         networkAgent.networkCapabilities, nri.mPid, nri.mUid));
-                putParcelable(bundle, new LinkProperties(networkAgent.linkProperties));
+                putParcelable(bundle, linkPropertiesRestrictedForCallerPermissions(
+                        networkAgent.linkProperties, nri.mPid, nri.mUid));
                 // For this notification, arg1 contains the blocked status.
                 msg.arg1 = arg1;
                 break;
@@ -6162,7 +6187,8 @@
                 break;
             }
             case ConnectivityManager.CALLBACK_IP_CHANGED: {
-                putParcelable(bundle, new LinkProperties(networkAgent.linkProperties));
+                putParcelable(bundle, linkPropertiesRestrictedForCallerPermissions(
+                        networkAgent.linkProperties, nri.mPid, nri.mUid));
                 break;
             }
             case ConnectivityManager.CALLBACK_BLK_CHANGED: {
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 1cae5f2..68574f5 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -289,7 +289,10 @@
 
     static final int PRECISE_PHONE_STATE_PERMISSION_MASK =
                 PhoneStateListener.LISTEN_PRECISE_CALL_STATE
-                | PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE;
+                | PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE
+                | PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES
+                | PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED
+                | PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES;
 
     static final int READ_ACTIVE_EMERGENCY_SESSION_PERMISSION_MASK =
             PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_CALL
@@ -2518,8 +2521,14 @@
         }
 
         if ((events & PRECISE_PHONE_STATE_PERMISSION_MASK) != 0) {
-            mContext.enforceCallingOrSelfPermission(
-                    android.Manifest.permission.READ_PRECISE_PHONE_STATE, null);
+            // check if calling app has either permission READ_PRECISE_PHONE_STATE
+            // or with carrier privileges
+            try {
+                mContext.enforceCallingOrSelfPermission(
+                        android.Manifest.permission.READ_PRECISE_PHONE_STATE, null);
+            } catch (SecurityException se) {
+                TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mContext, subId, message);
+            }
         }
 
         if ((events & READ_ACTIVE_EMERGENCY_SESSION_PERMISSION_MASK) != 0) {
@@ -2542,16 +2551,6 @@
                     android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null);
         }
 
-        if ((events & PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES) != 0) {
-            mContext.enforceCallingOrSelfPermission(
-                    android.Manifest.permission.READ_PRECISE_PHONE_STATE, null);
-        }
-
-        if ((events & PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED) != 0) {
-            mContext.enforceCallingOrSelfPermission(
-                    android.Manifest.permission.READ_PRECISE_PHONE_STATE, null);
-        }
-
         if ((events & PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED) != 0) {
             mContext.enforceCallingOrSelfPermission(
                     android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null);
@@ -2562,11 +2561,6 @@
                     android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null);
         }
 
-        if ((events & PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES) != 0) {
-            mContext.enforceCallingOrSelfPermission(
-                    android.Manifest.permission.READ_PRECISE_PHONE_STATE, null);
-        }
-
         return true;
     }
 
diff --git a/services/core/java/com/android/server/adb/AdbService.java b/services/core/java/com/android/server/adb/AdbService.java
index 7fd98e0..c125b1b 100644
--- a/services/core/java/com/android/server/adb/AdbService.java
+++ b/services/core/java/com/android/server/adb/AdbService.java
@@ -17,6 +17,7 @@
 
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.database.ContentObserver;
 import android.debug.AdbManagerInternal;
 import android.debug.IAdbManager;
@@ -260,6 +261,30 @@
         }
     }
 
+    /**
+     * @return true if the device supports secure ADB over Wi-Fi.
+     * @hide
+     */
+    @Override
+    public boolean isAdbWifiSupported() {
+        mContext.enforceCallingPermission(
+                android.Manifest.permission.MANAGE_DEBUGGING, "AdbService");
+        return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI);
+    }
+
+    /**
+     * @return true if the device supports secure ADB over Wi-Fi and device pairing by
+     * QR code.
+     * @hide
+     */
+    @Override
+    public boolean isAdbWifiQrSupported() {
+        mContext.enforceCallingPermission(
+                android.Manifest.permission.MANAGE_DEBUGGING, "AdbService");
+        return isAdbWifiSupported() && mContext.getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_CAMERA_ANY);
+    }
+
     private void setAdbEnabled(boolean enable) {
         if (DEBUG) Slog.d(TAG, "setAdbEnabled(" + enable + "), mAdbEnabled=" + mAdbEnabled);
 
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 3ffa5de..ac85bf5 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -31,6 +31,7 @@
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
 import android.app.ActivityThread;
@@ -2068,9 +2069,9 @@
         if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "retrieveServiceLocked: " + service
                 + " type=" + resolvedType + " callingUid=" + callingUid);
 
-        userId = mAm.mUserController.handleIncomingUser(callingPid, callingUid, userId, false,
-                ActivityManagerInternal.ALLOW_ALL_PROFILE_PERMISSIONS_IN_PROFILE, "service",
-                callingPackage);
+        userId = mAm.mUserController.handleIncomingUser(callingPid, callingUid, userId,
+                /* allowAll= */false, getAllowMode(service, callingPackage),
+                /* name= */ "service", callingPackage);
 
         ServiceMap smap = getServiceMapLocked(userId);
         final ComponentName comp;
@@ -2260,6 +2261,17 @@
         return null;
     }
 
+    private int getAllowMode(Intent service, @Nullable String callingPackage) {
+        if (callingPackage == null || service.getComponent() == null) {
+            return ActivityManagerInternal.ALLOW_NON_FULL_IN_PROFILE;
+        }
+        if (callingPackage.equals(service.getComponent().getPackageName())) {
+            return ActivityManagerInternal.ALLOW_ALL_PROFILE_PERMISSIONS_IN_PROFILE;
+        } else {
+            return ActivityManagerInternal.ALLOW_NON_FULL_IN_PROFILE;
+        }
+    }
+
     private final void bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why) {
         if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, ">>> EXECUTING "
                 + why + " of " + r + " in app " + r.app);
diff --git a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
index 549051d..60754fb 100644
--- a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
+++ b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
@@ -32,8 +32,8 @@
 import android.graphics.RectF;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
-import android.os.Build;
 import android.os.UserManager;
+import android.provider.Settings;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.ImageView;
@@ -83,9 +83,13 @@
         }
 
         TextView msgView = view.findViewById(R.id.user_loading);
-        // TODO: use developer settings instead
-        if (Build.IS_DEBUGGABLE) {
-            // TODO: use specific string
+
+        // TODO(b/145132885): use constant from CarSettings
+        boolean showInfo = "true".equals(Settings.Global.getString(
+                getContext().getContentResolver(),
+                "android.car.ENABLE_USER_SWITCH_DEVELOPER_MESSAGE"));
+
+        if (showInfo) {
             msgView.setText(res.getString(R.string.car_loading_profile) + " user\n(from "
                     + mOldUser.id + " to " + mNewUser.id + ")");
         } else {
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 7f9477ed..4a89845 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -91,9 +91,7 @@
 import android.os.storage.StorageManager;
 import android.os.storage.StorageManagerInternal;
 import android.provider.DeviceConfig;
-import android.system.ErrnoException;
 import android.system.Os;
-import android.system.OsConstants;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.EventLog;
@@ -327,12 +325,7 @@
     /**
      * How long between a process kill and we actually receive its death recipient
      */
-    private static final long PROC_KILL_TIMEOUT = 2000; // 2 seconds;
-
-    /**
-     * How long between polls to check if the given process is dead or not.
-     */
-    private static final long PROC_DEATH_POLL_INTERVAL = 100;
+    private static final int PROC_KILL_TIMEOUT = 2000; // 2 seconds;
 
     ActivityManagerService mService = null;
 
@@ -2169,28 +2162,6 @@
     }
 
     /**
-     * A lite version of checking if a process is alive or not, by using kill(2) with signal 0.
-     *
-     * <p>
-     * Note that, zombie processes are stil "alive" in this case, use the {@link
-     * ActivityManagerService#isProcessAliveLocked} if zombie processes need to be excluded.
-     * </p>
-     */
-    @GuardedBy("mService")
-    private boolean isProcessAliveLiteLocked(ProcessRecord app) {
-        // If somehow the pid is invalid, let's think it's dead.
-        if (app.pid <= 0) {
-            return false;
-        }
-        try {
-            Os.kill(app.pid, 0);
-        } catch (ErrnoException e) {
-            return e.errno != OsConstants.ESRCH;
-        }
-        return true;
-    }
-
-    /**
      * Kill (if asked to) and wait for the given process died if necessary
      * @param app - The process record to kill
      * @param doKill - Kill the given process record
@@ -2214,20 +2185,9 @@
 
         // wait for the death
         if (wait) {
-            boolean isAlive = true;
-            // ideally we should use pidfd_open(2) but it's available on kernel 5.3 or later
-
-            final long timeout = SystemClock.uptimeMillis() + PROC_KILL_TIMEOUT;
-            isAlive = isProcessAliveLiteLocked(app);
-            while (timeout > SystemClock.uptimeMillis() && isAlive) {
-                try {
-                    Thread.sleep(PROC_DEATH_POLL_INTERVAL);
-                } catch (InterruptedException e) {
-                }
-                isAlive = isProcessAliveLiteLocked(app);
-            }
-
-            if (isAlive) {
+            try {
+                Process.waitForProcessDeath(app.pid, PROC_KILL_TIMEOUT);
+            } catch (Exception e) {
                 // Maybe the process goes into zombie, use an expensive API to check again.
                 if (mService.isProcessAliveLocked(app)) {
                     Slog.w(TAG, String.format(formatString,
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index eedeeea..46972d9 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -63,6 +63,7 @@
 import android.hardware.usb.UsbManager;
 import android.hidl.manager.V1_0.IServiceManager;
 import android.media.AudioAttributes;
+import android.media.AudioAttributes.AttributeSystemUsage;
 import android.media.AudioDeviceAddress;
 import android.media.AudioDeviceInfo;
 import android.media.AudioFocusInfo;
@@ -570,6 +571,11 @@
     @GuardedBy("mSettingsLock")
     private int mAssistantUid;
 
+    private final Object mSupportedSystemUsagesLock = new Object();
+    @GuardedBy("mSupportedSystemUsagesLock")
+    private @AttributeSystemUsage int[] mSupportedSystemUsages =
+            new int[]{AudioAttributes.USAGE_CALL_ASSISTANT};
+
     // Defines the format for the connection "address" for ALSA devices
     public static String makeAlsaAddressString(int card, int device) {
         return "card=" + card + ";device=" + device + ";";
@@ -1043,6 +1049,10 @@
             }
         }
 
+        synchronized (mSupportedSystemUsagesLock) {
+            AudioSystem.setSupportedSystemUsages(mSupportedSystemUsages);
+        }
+
         synchronized (mAudioPolicies) {
             for (AudioPolicyProxy policy : mAudioPolicies.values()) {
                 final int status = policy.connectMixes();
@@ -1099,6 +1109,37 @@
     }
 
     /**
+     * @see AudioManager#setSupportedSystemUsages(int[])
+     */
+    public void setSupportedSystemUsages(@NonNull @AttributeSystemUsage int[] systemUsages) {
+        enforceModifyAudioRoutingPermission();
+        verifySystemUsages(systemUsages);
+
+        synchronized (mSupportedSystemUsagesLock) {
+            AudioSystem.setSupportedSystemUsages(systemUsages);
+            mSupportedSystemUsages = systemUsages;
+        }
+    }
+
+    /**
+     * @see AudioManager#getSupportedSystemUsages()
+     */
+    public @NonNull @AttributeSystemUsage int[] getSupportedSystemUsages() {
+        enforceModifyAudioRoutingPermission();
+        synchronized (mSupportedSystemUsagesLock) {
+            return Arrays.copyOf(mSupportedSystemUsages, mSupportedSystemUsages.length);
+        }
+    }
+
+    private void verifySystemUsages(@NonNull int[] systemUsages) {
+        for (int i = 0; i < systemUsages.length; i++) {
+            if (!AudioAttributes.isSystemUsage(systemUsages[i])) {
+                throw new IllegalArgumentException("Non-system usage provided: " + systemUsages[i]);
+            }
+        }
+    }
+
+    /**
      * @return the {@link android.media.audiopolicy.AudioProductStrategy} discovered from the
      * platform configuration file.
      */
@@ -5720,10 +5761,48 @@
         return false;
     }
 
+    private boolean isSupportedSystemUsage(@AudioAttributes.AttributeUsage int usage) {
+        synchronized (mSupportedSystemUsagesLock) {
+            for (int i = 0; i < mSupportedSystemUsages.length; i++) {
+                if (mSupportedSystemUsages[i] == usage) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    private void validateAudioAttributesUsage(@NonNull AudioAttributes audioAttributes) {
+        @AudioAttributes.AttributeUsage int usage = audioAttributes.getSystemUsage();
+        if (AudioAttributes.isSystemUsage(usage)) {
+            if (callerHasPermission(Manifest.permission.MODIFY_AUDIO_ROUTING)) {
+                if (!isSupportedSystemUsage(usage)) {
+                    throw new IllegalArgumentException(
+                            "Unsupported usage " + AudioAttributes.usageToString(usage));
+                }
+            } else {
+                throw new SecurityException("Missing MODIFY_AUDIO_ROUTING permission");
+            }
+        }
+    }
+
+    private boolean isValidAudioAttributesUsage(@NonNull AudioAttributes audioAttributes) {
+        @AudioAttributes.AttributeUsage int usage = audioAttributes.getSystemUsage();
+        if (AudioAttributes.isSystemUsage(usage)) {
+            return callerHasPermission(Manifest.permission.MODIFY_AUDIO_ROUTING)
+                    && isSupportedSystemUsage(usage);
+        }
+        return true;
+    }
+
     public int requestAudioFocus(AudioAttributes aa, int durationHint, IBinder cb,
             IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags,
             IAudioPolicyCallback pcb, int sdk) {
         // permission checks
+        if (aa != null && !isValidAudioAttributesUsage(aa)) {
+            Log.w(TAG, "Request using unsupported usage.");
+            return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+        }
         if ((flags & AudioManager.AUDIOFOCUS_FLAG_LOCK) == AudioManager.AUDIOFOCUS_FLAG_LOCK) {
             if (AudioSystem.IN_VOICE_COMM_FOCUS_ID.equals(clientId)) {
                 if (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(
@@ -5754,6 +5833,10 @@
 
     public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, AudioAttributes aa,
             String callingPackageName) {
+        if (aa != null && !isValidAudioAttributesUsage(aa)) {
+            Log.w(TAG, "Request using unsupported usage.");
+            return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+        }
         return mMediaFocusControl.abandonAudioFocus(fd, clientId, aa, callingPackageName);
     }
 
@@ -6313,6 +6396,17 @@
         sForceUseLogger.dump(pw);
         pw.println("\n");
         sVolumeLogger.dump(pw);
+        pw.println("\n");
+        dumpSupportedSystemUsage(pw);
+    }
+
+    private void dumpSupportedSystemUsage(PrintWriter pw) {
+        pw.println("Supported System Usages:");
+        synchronized (mSupportedSystemUsagesLock) {
+            for (int i = 0; i < mSupportedSystemUsages.length; i++) {
+                pw.printf("\t%s\n", AudioAttributes.usageToString(mSupportedSystemUsages[i]));
+            }
+        }
     }
 
     private static String safeMediaVolumeStateToString(int state) {
@@ -7090,10 +7184,16 @@
     }
 
     public int trackPlayer(PlayerBase.PlayerIdCard pic) {
+        if (pic != null && pic.mAttributes != null) {
+            validateAudioAttributesUsage(pic.mAttributes);
+        }
         return mPlaybackMonitor.trackPlayer(pic);
     }
 
     public void playerAttributes(int piid, AudioAttributes attr) {
+        if (attr != null) {
+            validateAudioAttributesUsage(attr);
+        }
         mPlaybackMonitor.playerAttributes(piid, attr, Binder.getCallingUid());
     }
 
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index c845981..7bf2bc8 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -727,6 +727,7 @@
             case AudioAttributes.USAGE_ASSISTANT:
             case AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY:
             case AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
+            case AudioAttributes.USAGE_ANNOUNCEMENT:
                 return 700;
             case AudioAttributes.USAGE_VOICE_COMMUNICATION:
             case AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING:
@@ -736,7 +737,10 @@
             case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
             case AudioAttributes.USAGE_NOTIFICATION_EVENT:
             case AudioAttributes.USAGE_ASSISTANCE_SONIFICATION:
+            case AudioAttributes.USAGE_VEHICLE_STATUS:
                 return 500;
+            case AudioAttributes.USAGE_EMERGENCY:
+            case AudioAttributes.USAGE_SAFETY:
             case AudioAttributes.USAGE_UNKNOWN:
             default:
                 return 0;
diff --git a/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java b/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java
index 96a202f..299cb66 100644
--- a/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java
+++ b/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java
@@ -81,9 +81,12 @@
         printEvent(localTimeMs, pw, mCurrentDefaultNetwork);
     }
 
-    public synchronized void listEventsAsProto(PrintWriter pw) {
+    /**
+     * Convert events in the ring buffer to protos and add to the given list
+     */
+    public synchronized void listEventsAsProto(List<IpConnectivityEvent> out) {
         for (DefaultNetworkEvent ev : mEventsLog.toArray()) {
-            pw.print(IpConnectivityEventBuilder.toProto(ev));
+            out.add(IpConnectivityEventBuilder.toProto(ev));
         }
     }
 
diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
index 33f6ed5..1337a93 100644
--- a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
+++ b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
@@ -41,7 +41,9 @@
 import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
 
 import java.io.FileDescriptor;
+import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.OutputStream;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -239,18 +241,37 @@
         mDefaultNetworkMetrics.listEvents(pw);
     }
 
+    private List<IpConnectivityEvent> listEventsAsProtos() {
+        final List<IpConnectivityEvent> events = IpConnectivityEventBuilder.toProto(getEvents());
+        if (mNetdListener != null) {
+            mNetdListener.listAsProtos(events);
+        }
+        mDefaultNetworkMetrics.listEventsAsProto(events);
+        return events;
+    }
+
     /*
      * Print the content of the rolling event buffer in text proto format.
      */
-    private void cmdListAsProto(PrintWriter pw) {
-        final List<ConnectivityMetricsEvent> events = getEvents();
-        for (IpConnectivityEvent ev : IpConnectivityEventBuilder.toProto(events)) {
-            pw.print(ev.toString());
+    private void cmdListAsTextProto(PrintWriter pw) {
+        listEventsAsProtos().forEach(e -> pw.print(e.toString()));
+    }
+
+    /*
+     * Write the content of the rolling event buffer in proto wire format to the given OutputStream.
+     */
+    private void cmdListAsBinaryProto(OutputStream out) {
+        final int dropped;
+        synchronized (mLock) {
+            dropped = mDropped;
         }
-        if (mNetdListener != null) {
-            mNetdListener.listAsProtos(pw);
+        try {
+            byte[] data = IpConnectivityEventBuilder.serialize(dropped, listEventsAsProtos());
+            out.write(data);
+            out.flush();
+        } catch (IOException e) {
+            Log.e(TAG, "could not serialize events", e);
         }
-        mDefaultNetworkMetrics.listEventsAsProto(pw);
     }
 
     /*
@@ -267,6 +288,9 @@
         static final String CMD_FLUSH = "flush";
         // Dump the rolling buffer of metrics event in human readable proto text format.
         static final String CMD_PROTO = "proto";
+        // Dump the rolling buffer of metrics event in proto wire format. See usage() of
+        // frameworks/native/cmds/dumpsys/dumpsys.cpp for details.
+        static final String CMD_PROTO_BIN = "--proto";
         // Dump the rolling buffer of metrics event and pretty print events using a human readable
         // format. Also print network dns/connect statistics and default network event time series.
         static final String CMD_LIST = "list";
@@ -291,7 +315,10 @@
                     cmdFlush(pw);
                     return;
                 case CMD_PROTO:
-                    cmdListAsProto(pw);
+                    cmdListAsTextProto(pw);
+                    return;
+                case CMD_PROTO_BIN:
+                    cmdListAsBinaryProto(new FileOutputStream(fd));
                     return;
                 case CMD_LIST:
                 default:
diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
index dbc339b..0d31051 100644
--- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
+++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
@@ -366,15 +366,18 @@
         }
     }
 
-    public synchronized void listAsProtos(PrintWriter pw) {
+    /**
+     * Convert events in the buffer to protos and add to the given list
+     */
+    public synchronized void listAsProtos(List<IpConnectivityEvent> out) {
         for (int i = 0; i < mNetworkMetrics.size(); i++) {
-            pw.print(IpConnectivityEventBuilder.toProto(mNetworkMetrics.valueAt(i).connectMetrics));
+            out.add(IpConnectivityEventBuilder.toProto(mNetworkMetrics.valueAt(i).connectMetrics));
         }
         for (int i = 0; i < mNetworkMetrics.size(); i++) {
-            pw.print(IpConnectivityEventBuilder.toProto(mNetworkMetrics.valueAt(i).dnsMetrics));
+            out.add(IpConnectivityEventBuilder.toProto(mNetworkMetrics.valueAt(i).dnsMetrics));
         }
         for (int i = 0; i < mWakeupStats.size(); i++) {
-            pw.print(IpConnectivityEventBuilder.toProto(mWakeupStats.valueAt(i)));
+            out.add(IpConnectivityEventBuilder.toProto(mWakeupStats.valueAt(i)));
         }
     }
 
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 0bf65bd..905a94f 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -758,6 +758,14 @@
     private final WeakHashMap<IBinder, IBinder> mImeTargetWindowMap = new WeakHashMap<>();
 
     /**
+     * Map of generated token to windowToken that is requesting
+     * {@link InputMethodManager#showSoftInput(View, int)}.
+     * This map tracks origin of showSoftInput requests.
+     */
+    @GuardedBy("mMethodMap")
+    private final WeakHashMap<IBinder, IBinder> mShowRequestWindowMap = new WeakHashMap<>();
+
+    /**
      * A ring buffer to store the history of {@link StartInputInfo}.
      */
     private static final class StartInputHistory {
@@ -974,7 +982,8 @@
                         hideCurrentInputLocked(0, null);
                         mShowRequested = showRequested;
                     } else if (mShowRequested) {
-                        showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
+                        showCurrentInputLocked(
+                                mCurFocusedWindow, InputMethodManager.SHOW_IMPLICIT, null);
                     }
                 } else {
                     boolean enabledChanged = false;
@@ -2075,7 +2084,7 @@
                 startInputToken, session, mCurInputContext, mCurAttribute));
         if (mShowRequested) {
             if (DEBUG) Slog.v(TAG, "Attach new input asks to show input");
-            showCurrentInputLocked(getAppShowFlags(), null);
+            showCurrentInputLocked(mCurFocusedWindow, getAppShowFlags(), null);
         }
         return new InputBindResult(InputBindResult.ResultCode.SUCCESS_WITH_IME_SESSION,
                 session.session, (session.channel != null ? session.channel.dup() : null),
@@ -2789,7 +2798,7 @@
     }
 
     @Override
-    public boolean showSoftInput(IInputMethodClient client, int flags,
+    public boolean showSoftInput(IInputMethodClient client, IBinder windowToken, int flags,
             ResultReceiver resultReceiver) {
         int uid = Binder.getCallingUid();
         synchronized (mMethodMap) {
@@ -2814,7 +2823,7 @@
                     }
                 }
                 if (DEBUG) Slog.v(TAG, "Client requesting input be shown");
-                return showCurrentInputLocked(flags, resultReceiver);
+                return showCurrentInputLocked(windowToken, flags, resultReceiver);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -2822,7 +2831,7 @@
     }
 
     @GuardedBy("mMethodMap")
-    boolean showCurrentInputLocked(int flags, ResultReceiver resultReceiver) {
+    boolean showCurrentInputLocked(IBinder windowToken, int flags, ResultReceiver resultReceiver) {
         mShowRequested = true;
         if (mAccessibilityRequestingNoSoftKeyboard) {
             return false;
@@ -2842,9 +2851,12 @@
         boolean res = false;
         if (mCurMethod != null) {
             if (DEBUG) Slog.d(TAG, "showCurrentInputLocked: mCurToken=" + mCurToken);
-            executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOO(
+            // create a dummy token for IMS so that IMS cannot inject windows into client app.
+            Binder showInputToken = new Binder();
+            mShowRequestWindowMap.put(showInputToken, windowToken);
+            executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOOO(
                     MSG_SHOW_SOFT_INPUT, getImeShowFlags(), mCurMethod,
-                    resultReceiver));
+                    resultReceiver, showInputToken));
             mInputShown = true;
             if (mHaveConnection && !mVisibleBound) {
                 bindCurrentInputMethodServiceLocked(
@@ -3145,7 +3157,7 @@
                                 attribute, startInputFlags, startInputReason);
                         didStart = true;
                     }
-                    showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
+                    showCurrentInputLocked(windowToken, InputMethodManager.SHOW_IMPLICIT, null);
                 }
                 break;
             case LayoutParams.SOFT_INPUT_STATE_UNCHANGED:
@@ -3171,7 +3183,7 @@
                                     attribute, startInputFlags, startInputReason);
                             didStart = true;
                         }
-                        showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
+                        showCurrentInputLocked(windowToken, InputMethodManager.SHOW_IMPLICIT, null);
                     } else {
                         Slog.e(TAG, "SOFT_INPUT_STATE_VISIBLE is ignored because"
                                 + " there is no focused view that also returns true from"
@@ -3188,7 +3200,7 @@
                                 attribute, startInputFlags, startInputReason);
                         didStart = true;
                     }
-                    showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
+                    showCurrentInputLocked(windowToken, InputMethodManager.SHOW_IMPLICIT, null);
                 } else {
                     Slog.e(TAG, "SOFT_INPUT_STATE_ALWAYS_VISIBLE is ignored because"
                             + " there is no focused view that also returns true from"
@@ -3627,7 +3639,7 @@
     }
 
     @BinderThread
-    private void applyImeVisibility(IBinder token, boolean setVisible) {
+    private void applyImeVisibility(IBinder token, IBinder windowToken, boolean setVisible) {
         synchronized (mMethodMap) {
             if (!calledWithValidTokenLocked(token)) {
                 return;
@@ -3644,7 +3656,7 @@
                 }
             } else {
                 // Send to window manager to show IME after IME layout finishes.
-                mWindowManagerInternal.showImePostLayout(mLastImeTargetWindow);
+                mWindowManagerInternal.showImePostLayout(mShowRequestWindowMap.get(windowToken));
             }
         }
     }
@@ -3695,7 +3707,7 @@
             }
             long ident = Binder.clearCallingIdentity();
             try {
-                showCurrentInputLocked(flags, null);
+                showCurrentInputLocked(mLastImeTargetWindow, flags, null);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -3780,7 +3792,8 @@
                 try {
                     if (DEBUG) Slog.v(TAG, "Calling " + args.arg1 + ".showSoftInput("
                             + msg.arg1 + ", " + args.arg2 + ")");
-                    ((IInputMethod)args.arg1).showSoftInput(msg.arg1, (ResultReceiver)args.arg2);
+                    ((IInputMethod) args.arg1).showSoftInput(
+                            (IBinder) args.arg3, msg.arg1, (ResultReceiver) args.arg2);
                 } catch (RemoteException e) {
                 }
                 args.recycle();
@@ -5346,8 +5359,8 @@
 
         @BinderThread
         @Override
-        public void applyImeVisibility(boolean setVisible) {
-            mImms.applyImeVisibility(mToken, setVisible);
+        public void applyImeVisibility(IBinder windowToken, boolean setVisible) {
+            mImms.applyImeVisibility(mToken, windowToken, setVisible);
         }
     }
 }
diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
index f09795f..d09c478 100644
--- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
@@ -1449,7 +1449,8 @@
         @BinderThread
         @Override
         public boolean showSoftInput(
-                IInputMethodClient client, int flags, ResultReceiver resultReceiver) {
+                IInputMethodClient client, IBinder token, int flags,
+                ResultReceiver resultReceiver) {
             final int callingUid = Binder.getCallingUid();
             final int callingPid = Binder.getCallingPid();
             final int userId = UserHandle.getUserId(callingUid);
diff --git a/services/core/java/com/android/server/media/BluetoothRouteProvider.java b/services/core/java/com/android/server/media/BluetoothRouteProvider.java
index 837c489..8179c32 100644
--- a/services/core/java/com/android/server/media/BluetoothRouteProvider.java
+++ b/services/core/java/com/android/server/media/BluetoothRouteProvider.java
@@ -29,12 +29,13 @@
 import android.content.IntentFilter;
 import android.media.MediaRoute2Info;
 import android.text.TextUtils;
-import android.util.Log;
+import android.util.Slog;
 import android.util.SparseBooleanArray;
 
 import com.android.internal.R;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -59,7 +60,6 @@
     private final BroadcastReceiver mBroadcastReceiver = new BluetoothBroadcastReceiver();
     private final BluetoothProfileListener mProfileListener = new BluetoothProfileListener();
 
-    // TODO: The mActiveDevice should be set when BluetoothRouteProvider is created.
     private BluetoothDevice mActiveDevice = null;
 
     static synchronized BluetoothRouteProvider getInstance(@NonNull Context context,
@@ -104,6 +104,43 @@
         mContext.registerReceiver(mBroadcastReceiver, mIntentFilter, null, null);
     }
 
+    /**
+     * Clears the active device for all known profiles.
+     */
+    public void clearActiveDevices() {
+        BluetoothA2dp a2dpProfile = mA2dpProfile;
+        BluetoothHearingAid hearingAidProfile = mHearingAidProfile;
+        if (a2dpProfile != null) {
+            a2dpProfile.setActiveDevice(null);
+        }
+        if (hearingAidProfile != null) {
+            hearingAidProfile.setActiveDevice(null);
+        }
+    }
+
+    /**
+     * Sets the active device.
+     * @param deviceId the id of the Bluetooth device
+     */
+    public void setActiveDevice(@NonNull String deviceId) {
+        BluetoothRouteInfo btRouteInfo = mBluetoothRoutes.get(deviceId);
+        if (btRouteInfo == null) {
+            Slog.w(TAG, "setActiveDevice: unknown device id=" + deviceId);
+            return;
+        }
+        BluetoothA2dp a2dpProfile = mA2dpProfile;
+        BluetoothHearingAid hearingAidProfile = mHearingAidProfile;
+
+        if (a2dpProfile != null
+                && btRouteInfo.connectedProfiles.get(BluetoothProfile.A2DP, false)) {
+            a2dpProfile.setActiveDevice(btRouteInfo.btDevice);
+        }
+        if (hearingAidProfile != null
+                && btRouteInfo.connectedProfiles.get(BluetoothProfile.HEARING_AID, false)) {
+            hearingAidProfile.setActiveDevice(btRouteInfo.btDevice);
+        }
+    }
+
     private void addEventReceiver(String action, BluetoothEventReceiver eventReceiver) {
         mEventReceiverMap.put(action, eventReceiver);
         mIntentFilter.addAction(action);
@@ -157,12 +194,12 @@
     private void setRouteConnectionStateForDevice(BluetoothDevice device,
             @MediaRoute2Info.ConnectionState int state) {
         if (device == null) {
-            Log.w(TAG, "setRouteConnectionStateForDevice: device shouldn't be null");
+            Slog.w(TAG, "setRouteConnectionStateForDevice: device shouldn't be null");
             return;
         }
         BluetoothRouteInfo btRoute = mBluetoothRoutes.get(device.getAddress());
         if (btRoute == null) {
-            Log.w(TAG, "setRouteConnectionStateForDevice: route shouldn't be null");
+            Slog.w(TAG, "setRouteConnectionStateForDevice: route shouldn't be null");
             return;
         }
         if (btRoute.route.getConnectionState() != state) {
@@ -184,24 +221,36 @@
     // These callbacks run on the main thread.
     private final class BluetoothProfileListener implements BluetoothProfile.ServiceListener {
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
+            List<BluetoothDevice> activeDevices;
             switch (profile) {
                 case BluetoothProfile.A2DP:
                     mA2dpProfile = (BluetoothA2dp) proxy;
+                    // It may contain null.
+                    activeDevices = Collections.singletonList(mA2dpProfile.getActiveDevice());
                     break;
                 case BluetoothProfile.HEARING_AID:
                     mHearingAidProfile = (BluetoothHearingAid) proxy;
+                    activeDevices = mHearingAidProfile.getActiveDevices();
                     break;
                 default:
                     return;
             }
+            //TODO: Check a pair of HAP devices whether there exist two or more active devices.
             for (BluetoothDevice device : proxy.getConnectedDevices()) {
                 BluetoothRouteInfo btRoute = mBluetoothRoutes.get(device.getAddress());
                 if (btRoute == null) {
                     btRoute = createBluetoothRoute(device);
                     mBluetoothRoutes.put(device.getAddress(), btRoute);
                 }
+                if (activeDevices.contains(device)) {
+                    mActiveDevice = device;
+                    setRouteConnectionStateForDevice(device,
+                            MediaRoute2Info.CONNECTION_STATE_CONNECTED);
+                }
+
                 btRoute.connectedProfiles.put(profile, true);
             }
+            notifyBluetoothRoutesUpdated();
         }
 
         public void onServiceDisconnected(int profile) {
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index f9169ee6..9594659 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -760,17 +760,12 @@
             Slog.w(TAG, "selectClientRouteLocked: Ignoring unknown manager.");
             return;
         }
-        //TODO: we shouldn't ignore selecting request for unknown clients. (RCN?)
         Client2Record clientRecord = managerRecord.mUserRecord.mHandler
                 .findClientforSessionLocked(sessionId);
-        if (clientRecord == null) {
-            Slog.w(TAG, "selectClientRouteLocked: Ignoring unknown session.");
-            return;
-        }
 
-        clientRecord.mUserRecord.mHandler.sendMessage(
+        managerRecord.mUserRecord.mHandler.sendMessage(
                 obtainMessage(UserHandler::selectRouteOnHandler,
-                            clientRecord.mUserRecord.mHandler,
+                            managerRecord.mUserRecord.mHandler,
                             clientRecord, sessionId, route));
     }
 
@@ -783,17 +778,12 @@
             Slog.w(TAG, "deselectClientRouteLocked: Ignoring unknown manager.");
             return;
         }
-        //TODO: we shouldn't ignore selecting request for unknown clients. (RCN?)
         Client2Record clientRecord = managerRecord.mUserRecord.mHandler
                 .findClientforSessionLocked(sessionId);
-        if (clientRecord == null) {
-            Slog.w(TAG, "deslectClientRouteLocked: Ignoring unknown session.");
-            return;
-        }
 
-        clientRecord.mUserRecord.mHandler.sendMessage(
+        managerRecord.mUserRecord.mHandler.sendMessage(
                 obtainMessage(UserHandler::deselectRouteOnHandler,
-                        clientRecord.mUserRecord.mHandler,
+                        managerRecord.mUserRecord.mHandler,
                         clientRecord, sessionId, route));
     }
 
@@ -806,17 +796,12 @@
             Slog.w(TAG, "transferClientRouteLocked: Ignoring unknown manager.");
             return;
         }
-        //TODO: we shouldn't ignore selecting request for unknown clients. (RCN?)
         Client2Record clientRecord = managerRecord.mUserRecord.mHandler
                 .findClientforSessionLocked(sessionId);
-        if (clientRecord == null) {
-            Slog.w(TAG, "transferClientRouteLocked: Ignoring unknown session.");
-            return;
-        }
 
-        clientRecord.mUserRecord.mHandler.sendMessage(
+        managerRecord.mUserRecord.mHandler.sendMessage(
                 obtainMessage(UserHandler::transferToRouteOnHandler,
-                        clientRecord.mUserRecord.mHandler,
+                        managerRecord.mUserRecord.mHandler,
                         clientRecord, sessionId, route));
     }
 
@@ -1166,7 +1151,7 @@
                     requestId, sessionHints);
         }
 
-        private void selectRouteOnHandler(@NonNull Client2Record clientRecord,
+        private void selectRouteOnHandler(@Nullable Client2Record clientRecord,
                 String uniqueSessionId, MediaRoute2Info route) {
             if (!checkArgumentsForSessionControl(clientRecord, uniqueSessionId, route,
                     "selecting")) {
@@ -1182,7 +1167,7 @@
             provider.selectRoute(getOriginalId(uniqueSessionId), route.getOriginalId());
         }
 
-        private void deselectRouteOnHandler(@NonNull Client2Record clientRecord,
+        private void deselectRouteOnHandler(@Nullable Client2Record clientRecord,
                 String uniqueSessionId, MediaRoute2Info route) {
             if (!checkArgumentsForSessionControl(clientRecord, uniqueSessionId, route,
                     "deselecting")) {
@@ -1198,7 +1183,7 @@
             provider.deselectRoute(getOriginalId(uniqueSessionId), route.getOriginalId());
         }
 
-        private void transferToRouteOnHandler(@NonNull Client2Record clientRecord,
+        private void transferToRouteOnHandler(Client2Record clientRecord,
                 String uniqueSessionId, MediaRoute2Info route) {
             if (!checkArgumentsForSessionControl(clientRecord, uniqueSessionId, route,
                     "transferring to")) {
@@ -1215,7 +1200,7 @@
                     route.getOriginalId());
         }
 
-        private boolean checkArgumentsForSessionControl(@NonNull Client2Record clientRecord,
+        private boolean checkArgumentsForSessionControl(@Nullable Client2Record clientRecord,
                 String uniqueSessionId, MediaRoute2Info route, @NonNull String description) {
             if (route == null) {
                 Slog.w(TAG, "Ignoring " + description + " null route");
@@ -1236,6 +1221,17 @@
                 return false;
             }
 
+            // Bypass checking client if it's the system session (clientRecord should be null)
+            if (TextUtils.equals(getProviderId(uniqueSessionId), mSystemProvider.getUniqueId())) {
+                return true;
+            }
+
+            //TODO: Handle RCN case.
+            if (clientRecord == null) {
+                Slog.w(TAG, "Ignoring " + description + " route from unknown client.");
+                return false;
+            }
+
             Client2Record matchingRecord = mSessionToClientMap.get(uniqueSessionId);
             if (matchingRecord != clientRecord) {
                 Slog.w(TAG, "Ignoring " + description + " route from non-matching client. "
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
index 6f6d8a1..558eb8d 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
@@ -64,7 +64,6 @@
             SystemMediaRoute2Provider.class.getPackageName$(),
             SystemMediaRoute2Provider.class.getName());
 
-    //TODO: Clean up these when audio manager support multiple bt devices
     MediaRoute2Info mDefaultRoute;
     @NonNull List<MediaRoute2Info> mBluetoothRoutes = Collections.EMPTY_LIST;
     final AudioRoutesInfo mCurAudioRoutesInfo = new AudioRoutesInfo();
@@ -91,6 +90,7 @@
         mAudioService = IAudioService.Stub.asInterface(
                 ServiceManager.getService(Context.AUDIO_SERVICE));
 
+        initializeDefaultRoute();
         mBtRouteProvider = BluetoothRouteProvider.getInstance(context, (routes) -> {
             mBluetoothRoutes = routes;
             publishRoutes();
@@ -103,7 +103,7 @@
                 notifySessionInfoUpdated();
             }
         });
-        initializeRoutes();
+        initializeSessionInfo();
     }
 
     @Override
@@ -119,17 +119,21 @@
 
     @Override
     public void selectRoute(String sessionId, String routeId) {
-        //TODO: implement method
+        // Do nothing since we don't support multiple BT yet.
     }
 
     @Override
     public void deselectRoute(String sessionId, String routeId) {
-        //TODO: implement method
+        // Do nothing since we don't support multiple BT yet.
     }
 
     @Override
     public void transferToRoute(String sessionId, String routeId) {
-        //TODO: implement method
+        if (TextUtils.equals(routeId, mDefaultRoute.getId())) {
+            mBtRouteProvider.clearActiveDevices();
+        } else {
+            mBtRouteProvider.setActiveDevice(routeId);
+        }
     }
 
     //TODO: implement method
@@ -147,8 +151,7 @@
     public void requestUpdateVolume(String routeId, int delta) {
     }
 
-    void initializeRoutes() {
-        //TODO: adds necessary info
+    private void initializeDefaultRoute() {
         mDefaultRoute = new MediaRoute2Info.Builder(
                 DEFAULT_ROUTE_ID,
                 mContext.getResources().getText(R.string.default_audio_route_name).toString())
@@ -172,7 +175,9 @@
             // route yet.
             updateAudioRoutes(newAudioRoutes);
         }
+    }
 
+    private void initializeSessionInfo() {
         mBluetoothRoutes = mBtRouteProvider.getBluetoothRoutes();
 
         MediaRoute2ProviderInfo.Builder builder = new MediaRoute2ProviderInfo.Builder();
@@ -183,11 +188,15 @@
         setProviderState(builder.build());
         mHandler.post(() -> notifyProviderState());
 
-        // Note: No lock needed when initializing.
-        updateSessionInfosIfNeededLocked();
+        //TODO: clean up this
+        // This is required because it is not instantiated in the main thread and
+        // BluetoothRoutesUpdatedListener can be called before this function
+        synchronized (mLock) {
+            updateSessionInfosIfNeededLocked();
+        }
     }
 
-    void updateAudioRoutes(AudioRoutesInfo newRoutes) {
+    private void updateAudioRoutes(AudioRoutesInfo newRoutes) {
         int name = R.string.default_audio_route_name;
         mCurAudioRoutesInfo.mainType = newRoutes.mainType;
         if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADPHONES) != 0
@@ -226,15 +235,22 @@
                 .setSystemSession(true);
         String activeBtDeviceAddress = mBtRouteProvider.getActiveDeviceAddress();
 
-        RoutingSessionInfo newSessionInfo;
         if (!TextUtils.isEmpty(activeBtDeviceAddress)) {
             // Bluetooth route. Set the route ID with the device's address.
-            newSessionInfo = builder.addSelectedRoute(activeBtDeviceAddress).build();
+            builder.addSelectedRoute(activeBtDeviceAddress);
+            builder.addTransferrableRoute(mDefaultRoute.getId());
         } else {
             // Default device
-            newSessionInfo = builder.addSelectedRoute(mDefaultRoute.getId()).build();
+            builder.addSelectedRoute(mDefaultRoute.getId());
         }
 
+        for (MediaRoute2Info route : mBluetoothRoutes) {
+            if (!TextUtils.equals(activeBtDeviceAddress, route.getId())) {
+                builder.addTransferrableRoute(route.getId());
+            }
+        }
+
+        RoutingSessionInfo newSessionInfo = builder.setProviderId(mUniqueId).build();
         if (Objects.equals(oldSessionInfo, newSessionInfo)) {
             return false;
         } else {
@@ -244,11 +260,6 @@
         }
     }
 
-    /**
-     * The first route should be the currently selected system route.
-     * For example, if there are two system routes (BT and device speaker),
-     * BT will be the first route in the list.
-     */
     void publishRoutes() {
         MediaRoute2ProviderInfo.Builder builder = new MediaRoute2ProviderInfo.Builder();
         builder.addRoute(mDefaultRoute);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index d0e4fe6..b5b3923 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -378,8 +378,9 @@
 
     /**
      * Apps that post custom toasts in the background will have those blocked. Apps can
-     * still post toasts created with {@link Toast#makeText(Context, CharSequence, int)} and its
-     * variants while in the background.
+     * still post toasts created with
+     * {@link android.widget.Toast#makeText(Context, CharSequence, int)} and its variants while
+     * in the background.
      *
      * TODO(b/144152069): Add @EnabledAfter(Q) to target R+ after assessing impact on dogfood
      */
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index 2807909..c6d2b33 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -66,7 +66,7 @@
  * ApexManager class handles communications with the apex service to perform operation and queries,
  * as well as providing caching to avoid unnecessary calls to the service.
  */
-abstract class ApexManager {
+public abstract class ApexManager {
 
     private static final String TAG = "ApexManager";
 
@@ -265,6 +265,13 @@
     abstract List<String> getApksInApex(String apexPackageName);
 
     /**
+     * Returns the apex module name for the given package name, if the package is an APEX. Otherwise
+     * returns {@code null}.
+     */
+    @Nullable
+    public abstract String getApexModuleNameForPackageName(String apexPackageName);
+
+    /**
      * Dumps various state information to the provided {@link PrintWriter} object.
      *
      * @param pw the {@link PrintWriter} object to send information to.
@@ -646,6 +653,15 @@
             }
         }
 
+        @Override
+        @Nullable
+        public String getApexModuleNameForPackageName(String apexPackageName) {
+            populatePackageNameToApexModuleNameIfNeeded();
+            synchronized (mLock) {
+                return mPackageNameToApexModuleName.get(apexPackageName);
+            }
+        }
+
         /**
          * Dump information about the packages contained in a particular cache
          * @param packagesCache the cache to print information about.
@@ -843,6 +859,12 @@
         }
 
         @Override
+        @Nullable
+        public String getApexModuleNameForPackageName(String apexPackageName) {
+            return null;
+        }
+
+        @Override
         void dump(PrintWriter pw, String packageName) {
             // No-op
         }
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index 3ed3534..78e1719 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -213,6 +213,25 @@
         return false;
     }
 
+    private static boolean canQueryViaPackage(AndroidPackage querying,
+            AndroidPackage potentialTarget) {
+        return querying.getQueriesPackages() != null
+                && querying.getQueriesPackages().contains(potentialTarget.getPackageName());
+    }
+
+    private static boolean canQueryAsInstaller(PackageSetting querying,
+            AndroidPackage potentialTarget) {
+        final InstallSource installSource = querying.installSource;
+        if (potentialTarget.getPackageName().equals(installSource.installerPackageName)) {
+            return true;
+        }
+        if (!installSource.isInitiatingPackageUninstalled
+                && potentialTarget.getPackageName().equals(installSource.initiatingPackageName)) {
+            return true;
+        }
+        return false;
+    }
+
     private static boolean matches(Intent intent, AndroidPackage potentialTarget) {
         for (int p = ArrayUtils.size(potentialTarget.getProviders()) - 1; p >= 0; p--) {
             ParsedProvider provider = potentialTarget.getProviders().get(p);
@@ -331,8 +350,8 @@
                     if (canQueryViaIntent(existingPkg, newPkg)) {
                         mQueriesViaIntent.add(existingSetting.appId, newPkgSetting.appId);
                     }
-                    if (existingPkg.getQueriesPackages() != null
-                            && existingPkg.getQueriesPackages().contains(newPkg.getPackageName())) {
+                    if (canQueryViaPackage(existingPkg, newPkg)
+                            || canQueryAsInstaller(existingSetting, newPkg)) {
                         mQueriesViaPackage.add(existingSetting.appId, newPkgSetting.appId);
                     }
                 }
@@ -341,8 +360,8 @@
                     if (canQueryViaIntent(newPkg, existingPkg)) {
                         mQueriesViaIntent.add(newPkgSetting.appId, existingSetting.appId);
                     }
-                    if (newPkg.getQueriesPackages() != null
-                            && newPkg.getQueriesPackages().contains(existingPkg.getPackageName())) {
+                    if (canQueryViaPackage(newPkg, existingPkg)
+                            || canQueryAsInstaller(newPkgSetting, existingPkg)) {
                         mQueriesViaPackage.add(newPkgSetting.appId, existingSetting.appId);
                     }
                 }
@@ -535,7 +554,6 @@
             try {
                 Trace.beginSection("mQueriesViaPackage");
                 if (mQueriesViaPackage.contains(callingAppId, targetAppId)) {
-                    // the calling package has explicitly declared the target package; allow
                     if (DEBUG_LOGGING) {
                         log(callingSetting, targetPkgSetting, "queries package");
                     }
diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
index 3635004..74d2efe 100644
--- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
+++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
@@ -173,6 +173,50 @@
     }
 
     @Override
+    public void startActivityAsUserByIntent(
+            IApplicationThread caller,
+            String callingPackage,
+            Intent intent,
+            @UserIdInt int userId) throws RemoteException {
+        Objects.requireNonNull(callingPackage);
+        Objects.requireNonNull(intent);
+        Objects.requireNonNull(intent.getComponent(), "The intent must have a Component set");
+
+        verifyCallingPackage(callingPackage);
+
+        final int callerUserId = mInjector.getCallingUserId();
+        final int callingUid = mInjector.getCallingUid();
+
+        List<UserHandle> allowedTargetUsers = getTargetUserProfilesUnchecked(
+                callingPackage, callerUserId);
+        if (callerUserId != userId && !allowedTargetUsers.contains(UserHandle.of(userId))) {
+            throw new SecurityException(callingPackage + " cannot access unrelated user " + userId);
+        }
+
+        Intent launchIntent = new Intent(intent);
+        launchIntent.setPackage(callingPackage);
+
+        if (!callingPackage.equals(launchIntent.getComponent().getPackageName())) {
+            throw new SecurityException(
+                    callingPackage + " attempts to start an activity in other package - "
+                            + launchIntent.getComponent().getPackageName());
+        }
+
+        if (callerUserId != userId) {
+            if (!hasInteractAcrossProfilesPermission(callingPackage)) {
+                throw new SecurityException("Attempt to launch activity without required "
+                        + android.Manifest.permission.INTERACT_ACROSS_PROFILES + " permission"
+                        + " or target user is not in the same profile group.");
+            }
+        }
+
+        verifyActivityCanHandleIntent(launchIntent, callingUid, userId);
+
+        mInjector.getActivityTaskManagerInternal().startActivityAsUser(
+                caller, callingPackage, launchIntent, /* options= */ null, userId);
+    }
+
+    @Override
     public boolean canRequestInteractAcrossProfiles(String callingPackage) {
         Objects.requireNonNull(callingPackage);
         verifyCallingPackage(callingPackage);
@@ -214,6 +258,11 @@
         if (targetUserProfiles.isEmpty()) {
             return false;
         }
+
+        return hasInteractAcrossProfilesPermission(callingPackage);
+    }
+
+    private boolean hasInteractAcrossProfilesPermission(String callingPackage) {
         final int callingUid = mInjector.getCallingUid();
         final int callingPid = mInjector.getCallingPid();
         return isPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS_FULL, callingUid)
@@ -237,21 +286,21 @@
     }
 
     private List<UserHandle> getTargetUserProfilesUnchecked(
-            String callingPackage, @UserIdInt int callingUserId) {
+            String packageName, @UserIdInt int userId) {
         final long ident = mInjector.clearCallingIdentity();
         try {
             final int[] enabledProfileIds =
-                    mInjector.getUserManager().getEnabledProfileIds(callingUserId);
+                    mInjector.getUserManager().getEnabledProfileIds(userId);
 
             List<UserHandle> targetProfiles = new ArrayList<>();
-            for (final int userId : enabledProfileIds) {
-                if (userId == callingUserId) {
+            for (final int profileId : enabledProfileIds) {
+                if (profileId == userId) {
                     continue;
                 }
-                if (!isPackageEnabled(callingPackage, userId)) {
+                if (!isPackageEnabled(packageName, profileId)) {
                     continue;
                 }
-                targetProfiles.add(UserHandle.of(userId));
+                targetProfiles.add(UserHandle.of(profileId));
             }
             return targetProfiles;
         } finally {
@@ -275,6 +324,27 @@
         }
     }
 
+    private void verifyActivityCanHandleIntent(
+            Intent launchIntent, int callingUid, @UserIdInt int userId) {
+        final long ident = mInjector.clearCallingIdentity();
+        try {
+            final List<ResolveInfo> activities =
+                    mInjector.getPackageManagerInternal().queryIntentActivities(
+                            launchIntent,
+                            launchIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
+                            MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
+                            callingUid,
+                            userId);
+
+            if (!activities.isEmpty()) {
+                return;
+            }
+            throw new SecurityException("Activity cannot handle intent");
+        } finally {
+            mInjector.restoreCallingIdentity(ident);
+        }
+    }
+
     /**
      * Verify that the specified intent does resolved to the specified component and the resolved
      * activity is exported.
@@ -315,14 +385,9 @@
                     "INTERACT_ACROSS_USERS or INTERACT_ACROSS_USERS_FULL is required to set the"
                             + " app-op for interacting across profiles.");
         }
-        if (!isPermissionGranted(Manifest.permission.MANAGE_APP_OPS_MODES, callingUid)) {
-            throw new SecurityException(
-                    "MANAGE_APP_OPS_MODES is required to set the app-op for interacting across"
-                            + " profiles.");
-        }
         final int callingUserId = mInjector.getCallingUserId();
         if (newMode == AppOpsManager.MODE_ALLOWED
-                && !canRequestInteractAcrossProfilesUnchecked(packageName, callingUserId)) {
+                && !canConfigureInteractAcrossProfiles(packageName)) {
             // The user should not be prompted for apps that cannot request to interact across
             // profiles. However, we return early here if required to avoid race conditions.
             Slog.e(TAG, "Tried to turn on the appop for interacting across profiles for invalid"
@@ -371,7 +436,7 @@
         final int uid = mInjector.getPackageManager()
                 .getPackageUidAsUser(packageName, /* flags= */ 0, userId);
         if (currentModeEquals(newMode, packageName, uid)) {
-            Slog.w(TAG,"Attempt to set mode to existing value of " + newMode + " for "
+            Slog.w(TAG, "Attempt to set mode to existing value of " + newMode + " for "
                     + packageName + " on user ID " + userId);
             return;
         }
@@ -392,18 +457,73 @@
 
     private void sendCanInteractAcrossProfilesChangedBroadcast(
             String packageName, int uid, UserHandle userHandle) {
-        final Intent intent = new Intent(ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED)
-                .setPackage(packageName);
-        if (!appDeclaresCrossProfileAttribute(uid)) {
+        final Intent intent =
+                new Intent(ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED).setPackage(packageName);
+        if (appDeclaresCrossProfileAttribute(uid)) {
+            intent.addFlags(
+                    Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND | Intent.FLAG_RECEIVER_FOREGROUND);
+        } else {
             intent.addFlags(FLAG_RECEIVER_REGISTERED_ONLY);
         }
-        mInjector.sendBroadcastAsUser(intent, userHandle);
+        for (ResolveInfo receiver : findBroadcastReceiversForUser(intent, userHandle)) {
+            intent.setComponent(receiver.getComponentInfo().getComponentName());
+            mInjector.sendBroadcastAsUser(intent, userHandle);
+        }
+    }
+
+    private List<ResolveInfo> findBroadcastReceiversForUser(Intent intent, UserHandle userHandle) {
+        return mInjector.getPackageManager()
+                .queryBroadcastReceiversAsUser(intent, /* flags= */ 0, userHandle);
     }
 
     private boolean appDeclaresCrossProfileAttribute(int uid) {
         return mInjector.getPackageManagerInternal().getPackage(uid).isCrossProfile();
     }
 
+    @Override
+    public boolean canConfigureInteractAcrossProfiles(String packageName) {
+        if (!hasOtherProfileWithPackageInstalled(packageName, mInjector.getCallingUserId())) {
+            return false;
+        }
+        if (!hasRequestedAppOpPermission(
+                AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName)) {
+            return false;
+        }
+        return isCrossProfilePackageWhitelisted(packageName);
+    }
+
+    private boolean hasOtherProfileWithPackageInstalled(String packageName, @UserIdInt int userId) {
+        final long ident = mInjector.clearCallingIdentity();
+        try {
+            final int[] profileIds =
+                    mInjector.getUserManager().getProfileIds(userId, /* enabledOnly= */ false);
+            for (int profileId : profileIds) {
+                if (profileId != userId && isPackageInstalled(packageName, profileId)) {
+                    return true;
+                }
+            }
+        } finally {
+            mInjector.restoreCallingIdentity(ident);
+        }
+        return false;
+    }
+
+    @Override
+    public void resetInteractAcrossProfilesAppOps(List<String> packageNames) {
+        packageNames.forEach(this::resetInteractAcrossProfilesAppOp);
+    }
+
+    private void resetInteractAcrossProfilesAppOp(String packageName) {
+        if (canConfigureInteractAcrossProfiles(packageName)) {
+            Slog.w(TAG, "Not resetting app-op for package " + packageName
+                    + " since it is still configurable by users.");
+            return;
+        }
+        final String op =
+                AppOpsManager.permissionToOp(Manifest.permission.INTERACT_ACROSS_PROFILES);
+        setInteractAcrossProfilesAppOp(packageName, AppOpsManager.opToDefaultMode(op));
+    }
+
     private boolean isSameProfileGroup(@UserIdInt int callerUserId, @UserIdInt int userId) {
         final long ident = mInjector.clearCallingIdentity();
         try {
diff --git a/services/core/java/com/android/server/pm/ModuleInfoProvider.java b/services/core/java/com/android/server/pm/ModuleInfoProvider.java
index 69510d9..06706cd 100644
--- a/services/core/java/com/android/server/pm/ModuleInfoProvider.java
+++ b/services/core/java/com/android/server/pm/ModuleInfoProvider.java
@@ -57,9 +57,9 @@
      */
     private static final String MODULE_METADATA_KEY = "android.content.pm.MODULE_METADATA";
 
-
     private final Context mContext;
     private final IPackageManager mPackageManager;
+    private final ApexManager mApexManager;
     private final Map<String, ModuleInfo> mModuleInfo;
 
     // TODO: Move this to an earlier boot phase if anybody requires it then.
@@ -69,13 +69,16 @@
     ModuleInfoProvider(Context context, IPackageManager packageManager) {
         mContext = context;
         mPackageManager = packageManager;
+        mApexManager = ApexManager.getInstance();
         mModuleInfo = new ArrayMap<>();
     }
 
     @VisibleForTesting
-    public ModuleInfoProvider(XmlResourceParser metadata, Resources resources) {
+    public ModuleInfoProvider(
+            XmlResourceParser metadata, Resources resources, ApexManager apexManager) {
         mContext = null;
         mPackageManager = null;
+        mApexManager = apexManager;
         mModuleInfo = new ArrayMap<>();
         loadModuleMetadata(metadata, resources);
     }
@@ -150,6 +153,8 @@
                 mi.setHidden(isHidden);
                 mi.setPackageName(modulePackageName);
                 mi.setName(moduleName);
+                mi.setApexModuleName(
+                        mApexManager.getApexModuleNameForPackageName(modulePackageName));
 
                 mModuleInfo.put(modulePackageName, mi);
             }
@@ -167,7 +172,7 @@
      *
      * @param flags Use {@link PackageManager#MATCH_ALL} flag to get all modules.
      */
-    List<ModuleInfo> getInstalledModules(@PackageManager.ModuleInfoFlags int flags) {
+    List<ModuleInfo> getInstalledModules(@PackageManager.InstalledModulesFlags int flags) {
         if (!mMetadataLoaded) {
             throw new IllegalStateException("Call to getInstalledModules before metadata loaded");
         }
@@ -195,12 +200,19 @@
         return installedModules;
     }
 
-    ModuleInfo getModuleInfo(String packageName, int flags) {
+    ModuleInfo getModuleInfo(String name, @PackageManager.ModuleInfoFlags int flags) {
         if (!mMetadataLoaded) {
             throw new IllegalStateException("Call to getModuleInfo before metadata loaded");
         }
-
-        return mModuleInfo.get(packageName);
+        if ((flags & PackageManager.MODULE_APEX_NAME) != 0) {
+            for (ModuleInfo moduleInfo : mModuleInfo.values()) {
+                if (name.equals(moduleInfo.getApexModuleName())) {
+                    return moduleInfo;
+                }
+            }
+            return null;
+        }
+        return mModuleInfo.get(name);
     }
 
     String getPackageName() {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index b1c38d1..10f46fd 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -259,11 +259,13 @@
         // atomic install which needs to query sessions, which requires lock on mSessions.
         boolean isDeviceUpgrading = mPm.isDeviceUpgrading();
         for (PackageInstallerSession session : stagedSessionsToRestore) {
-            if (isDeviceUpgrading && !session.isStagedAndInTerminalState()) {
+            if (!session.isStagedAndInTerminalState() && session.hasParentSessionId()
+                    && getSession(session.getParentSessionId()) == null) {
                 session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
-                        "Build fingerprint has changed");
+                        "An orphan staged session " + session.sessionId + " is found, "
+                                + "parent " + session.getParentSessionId() + " is missing");
             }
-            mStagingManager.restoreSession(session);
+            mStagingManager.restoreSession(session, isDeviceUpgrading);
         }
         // Broadcasts are not sent while we restore sessions on boot, since no processes would be
         // ready to listen to them. From now on, we greedily assume that broadcasts requests are
@@ -400,10 +402,10 @@
         } finally {
             IoUtils.closeQuietly(fis);
         }
-        // Re-sealing the sealed sessions.
+        // After all of the sessions were loaded, they are ready to be sealed and validated
         for (int i = 0; i < mSessions.size(); ++i) {
             PackageInstallerSession session = mSessions.valueAt(i);
-            session.sealIfNecessary();
+            session.sealAndValidateIfNecessary();
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 78875da..ed955a2 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1360,13 +1360,15 @@
     }
 
     /**
-     * If session should be sealed, then it's sealed to prevent further modification.
-     * If the session can't be sealed then it's destroyed.
+     * If session should be sealed, then it's sealed to prevent further modification
+     * and then it's validated.
+     *
+     * If the session was sealed but something went wrong then it's destroyed.
      *
      * <p> This is meant to be called after all of the sessions are loaded and added to
      * PackageInstallerService
      */
-    void sealIfNecessary() {
+    void sealAndValidateIfNecessary() {
         synchronized (mLock) {
             if (!mShouldBeSealed || isStagedAndInTerminalState()) {
                 return;
@@ -1375,7 +1377,9 @@
         List<PackageInstallerSession> childSessions = getChildSessions();
         synchronized (mLock) {
             try {
-                sealLocked(childSessions);
+                sealAndValidateLocked(childSessions);
+            } catch (StreamingException e) {
+                Slog.e(TAG, "Streaming failed", e);
             } catch (PackageManagerException e) {
                 Slog.e(TAG, "Package not valid", e);
             }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 07aec4a..3a33313 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -13494,6 +13494,7 @@
             // Okay!
             targetPackageSetting.setInstallerPackageName(installerPackageName);
             mSettings.addInstallerPackageNames(targetPackageSetting.installSource);
+            mAppsFilter.addPackage(targetPackageSetting, mSettings.mPackages);
             scheduleWriteSettingsLocked();
         }
     }
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index ad4f6ff..8384006 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -1227,7 +1227,7 @@
             }
             abandonSession = false;
 
-            if (!params.sessionParams.isStaged || !params.waitForStagedSessionReady) {
+            if (!params.sessionParams.isStaged || !params.mWaitForStagedSessionReady) {
                 pw.println("Success");
                 return 0;
             }
@@ -1265,7 +1265,7 @@
                         + si.getStagedSessionErrorMessage() + "]");
                 return 1;
             }
-            pw.println("Success");
+            pw.println("Success. Reboot device to apply staged session");
             return 0;
         } finally {
             if (abandonSession) {
@@ -2615,7 +2615,7 @@
         SessionParams sessionParams;
         String installerPackageName;
         int userId = UserHandle.USER_ALL;
-        boolean waitForStagedSessionReady = false;
+        boolean mWaitForStagedSessionReady = true;
         long timeoutMs = DEFAULT_WAIT_MS;
     }
 
@@ -2743,13 +2743,16 @@
                     sessionParams.installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
                     break;
                 case "--wait":
-                    params.waitForStagedSessionReady = true;
+                    params.mWaitForStagedSessionReady = true;
                     try {
                         params.timeoutMs = Long.parseLong(peekNextArg());
                         getNextArg();
                     } catch (NumberFormatException ignore) {
                     }
                     break;
+                case "--no-wait":
+                    params.mWaitForStagedSessionReady = false;
+                    break;
                 default:
                     throw new IllegalArgumentException("Unknown option " + opt);
             }
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 7888d1f..74c98f9 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -889,7 +889,7 @@
         return false;
     }
 
-    void restoreSession(@NonNull PackageInstallerSession session) {
+    void restoreSession(@NonNull PackageInstallerSession session, boolean isDeviceUpgrading) {
         PackageInstallerSession sessionToResume = session;
         synchronized (mStagedSessions) {
             mStagedSessions.append(session.sessionId, session);
@@ -906,6 +906,13 @@
                 }
             }
         }
+        // The preconditions used during pre-reboot verification might have changed when device
+        // is upgrading. Updated staged sessions to activation failed before we resume the session.
+        if (isDeviceUpgrading && !sessionToResume.isStagedAndInTerminalState()) {
+            sessionToResume.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
+                        "Build fingerprint has changed");
+            return;
+        }
         checkStateAndResume(sessionToResume);
     }
 
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index c1b71aa..ca36869 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -16,6 +16,8 @@
 
 package com.android.server.power;
 
+import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT;
+import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
 import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP;
 import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE;
 import static android.os.PowerManagerInternal.WAKEFULNESS_DOZING;
@@ -72,6 +74,7 @@
 import android.service.dreams.DreamManagerInternal;
 import android.service.vr.IVrManager;
 import android.service.vr.IVrStateCallbacks;
+import android.util.ArraySet;
 import android.util.KeyValueListParser;
 import android.util.PrintWriterPrinter;
 import android.util.Slog;
@@ -109,6 +112,7 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
+import java.util.Set;
 
 /**
  * The power manager service is responsible for coordinating power management
@@ -565,6 +569,9 @@
     // but the DreamService has not yet been told to start (it's an async process).
     private boolean mDozeStartInProgress;
 
+    // Set of all tokens suppressing ambient display.
+    private final Set<String> mAmbientDisplaySuppressionTokens = new ArraySet<>();
+
     private final class ForegroundProfileObserver extends SynchronousUserSwitchObserver {
         @Override
         public void onUserSwitching(@UserIdInt int newUserId) throws RemoteException {
@@ -844,7 +851,8 @@
 
     @Override
     public void onStart() {
-        publishBinderService(Context.POWER_SERVICE, mBinderService);
+        publishBinderService(Context.POWER_SERVICE, mBinderService, /* allowIsolated= */ false,
+                DUMP_FLAG_PRIORITY_DEFAULT | DUMP_FLAG_PRIORITY_CRITICAL);
         publishLocalService(PowerManagerInternal.class, mLocalService);
 
         Watchdog.getInstance().addMonitor(this);
@@ -3357,6 +3365,26 @@
         }
     }
 
+    private void suppressAmbientDisplayInternal(String token, boolean suppress) {
+        if (DEBUG_SPEW) {
+            Slog.d(TAG, "Suppress ambient display for token " + token + ": " + suppress);
+        }
+
+        if (suppress) {
+            mAmbientDisplaySuppressionTokens.add(token);
+        } else {
+            mAmbientDisplaySuppressionTokens.remove(token);
+        }
+
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                Settings.Secure.SUPPRESS_DOZE,
+                Math.min(mAmbientDisplaySuppressionTokens.size(), 1));
+    }
+
+    private String createAmbientDisplayToken(String token, int callingUid) {
+        return callingUid + "_" + token;
+    }
+
     private void boostScreenBrightnessInternal(long eventTime, int uid) {
         synchronized (mLock) {
             if (!mSystemReady || mWakefulness == WAKEFULNESS_ASLEEP
@@ -5007,6 +5035,61 @@
         }
 
         @Override // Binder call
+        public boolean isAmbientDisplayAvailable() {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.READ_DREAM_STATE, null);
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                return mAmbientDisplayConfiguration.ambientDisplayAvailable();
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override // Binder call
+        public void suppressAmbientDisplay(@NonNull String token, boolean suppress) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.WRITE_DREAM_STATE, null);
+
+            final int uid = Binder.getCallingUid();
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                suppressAmbientDisplayInternal(createAmbientDisplayToken(token, uid), suppress);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override // Binder call
+        public boolean isAmbientDisplaySuppressedForToken(@NonNull String token) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.READ_DREAM_STATE, null);
+
+            final int uid = Binder.getCallingUid();
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                return mAmbientDisplaySuppressionTokens.contains(
+                        createAmbientDisplayToken(token, uid));
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override // Binder call
+        public boolean isAmbientDisplaySuppressed() {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.READ_DREAM_STATE, null);
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                return mAmbientDisplaySuppressionTokens.size() > 0;
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override // Binder call
         public void boostScreenBrightness(long eventTime) {
             if (eventTime > SystemClock.uptimeMillis()) {
                 throw new IllegalArgumentException("event time must not be in the future");
diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
index 6686de9..951f1a4 100644
--- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
+++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
@@ -28,6 +28,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageManager;
 import android.content.pm.VersionedPackage;
@@ -45,20 +46,21 @@
 import android.util.Slog;
 import android.util.StatsLog;
 
-import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.server.PackageWatchdog;
 import com.android.server.PackageWatchdog.FailureReasons;
 import com.android.server.PackageWatchdog.PackageHealthObserver;
 import com.android.server.PackageWatchdog.PackageHealthObserverImpact;
 
-import libcore.io.IoUtils;
-
+import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileOutputStream;
+import java.io.FileReader;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 
@@ -72,11 +74,12 @@
 public final class RollbackPackageHealthObserver implements PackageHealthObserver {
     private static final String TAG = "RollbackPackageHealthObserver";
     private static final String NAME = "rollback-observer";
-    private static final int INVALID_ROLLBACK_ID = -1;
+
+    private static final String LOGGING_PARENT_KEY = "android.content.pm.LOGGING_PARENT";
 
     private final Context mContext;
     private final Handler mHandler;
-    private final File mLastStagedRollbackIdFile;
+    private final File mLastStagedRollbackIdsFile;
     // Staged rollback ids that have been committed but their session is not yet ready
     @GuardedBy("mPendingStagedRollbackIds")
     private final Set<Integer> mPendingStagedRollbackIds = new ArraySet<>();
@@ -88,7 +91,7 @@
         mHandler = handlerThread.getThreadHandler();
         File dataDir = new File(Environment.getDataDirectory(), "rollback-observer");
         dataDir.mkdirs();
-        mLastStagedRollbackIdFile = new File(dataDir, "last-staged-rollback-id");
+        mLastStagedRollbackIdsFile = new File(dataDir, "last-staged-rollback-ids");
         PackageWatchdog.getInstance(mContext).registerHealthObserver(this);
     }
 
@@ -150,22 +153,25 @@
 
     private void onBootCompleted() {
         RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class);
-        PackageInstaller packageInstaller = mContext.getPackageManager().getPackageInstaller();
-        String moduleMetadataPackageName = getModuleMetadataPackageName();
-
         if (!rollbackManager.getAvailableRollbacks().isEmpty()) {
             // TODO(gavincorkery): Call into Package Watchdog from outside the observer
             PackageWatchdog.getInstance(mContext).scheduleCheckAndMitigateNativeCrashes();
         }
 
-        int rollbackId = popLastStagedRollbackId();
-        if (rollbackId == INVALID_ROLLBACK_ID) {
-            // No staged rollback before reboot
-            return;
+        List<Integer> rollbackIds = popLastStagedRollbackIds();
+        Iterator<Integer> rollbackIterator = rollbackIds.iterator();
+        while (rollbackIterator.hasNext()) {
+            int rollbackId = rollbackIterator.next();
+            logRollbackStatusOnBoot(rollbackId, rollbackManager.getRecentlyCommittedRollbacks());
         }
+    }
+
+    private void logRollbackStatusOnBoot(int rollbackId,
+            List<RollbackInfo> recentlyCommittedRollbacks) {
+        PackageInstaller packageInstaller = mContext.getPackageManager().getPackageInstaller();
 
         RollbackInfo rollback = null;
-        for (RollbackInfo info : rollbackManager.getRecentlyCommittedRollbacks()) {
+        for (RollbackInfo info : recentlyCommittedRollbacks) {
             if (rollbackId == info.getRollbackId()) {
                 rollback = info;
                 break;
@@ -177,13 +183,26 @@
             return;
         }
 
-        // Use the version of the metadata package that was installed before
-        // we rolled back for logging purposes.
-        VersionedPackage oldLogPackage = null;
+        // Identify the logging parent for this rollback. When all configurations are correct, each
+        // package in the rollback refers to the same logging parent, except for the logging parent
+        // itself. If a logging parent is missing for a package, we use the package itself for
+        // logging. This might result in over-logging, but we prefer this over no logging.
+        final Set<String> loggingPackageNames = new ArraySet<>();
         for (PackageRollbackInfo packageRollback : rollback.getPackages()) {
-            if (packageRollback.getPackageName().equals(moduleMetadataPackageName)) {
-                oldLogPackage = packageRollback.getVersionRolledBackFrom();
-                break;
+            final String loggingParentName = getLoggingParentName(packageRollback.getPackageName());
+            if (loggingParentName != null) {
+                loggingPackageNames.add(loggingParentName);
+            } else {
+                loggingPackageNames.add(packageRollback.getPackageName());
+            }
+        }
+
+        // Use the version of the logging parent that was installed before
+        // we rolled back for logging purposes.
+        final List<VersionedPackage> oldLoggingPackages = new ArrayList<>();
+        for (PackageRollbackInfo packageRollback : rollback.getPackages()) {
+            if (loggingPackageNames.contains(packageRollback.getPackageName())) {
+                oldLoggingPackages.add(packageRollback.getVersionRolledBackFrom());
             }
         }
 
@@ -193,16 +212,17 @@
             Slog.e(TAG, "On boot completed, could not load session id " + sessionId);
             return;
         }
-        if (sessionInfo.isStagedSessionApplied()) {
-            logEvent(oldLogPackage,
-                    StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS,
-                    WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN, "");
-        } else if (sessionInfo.isStagedSessionReady()) {
-            // TODO: What do for staged session ready but not applied
-        } else {
-            logEvent(oldLogPackage,
-                    StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE,
-                    WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN, "");
+
+        for (VersionedPackage oldLoggingPackage : oldLoggingPackages) {
+            if (sessionInfo.isStagedSessionApplied()) {
+                logEvent(oldLoggingPackage,
+                        StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS,
+                        WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN, "");
+            } else if (sessionInfo.isStagedSessionFailed()) {
+                logEvent(oldLoggingPackage,
+                        StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE,
+                        WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN, "");
+            }
         }
     }
 
@@ -236,27 +256,17 @@
     }
 
     @Nullable
-    private String getModuleMetadataPackageName() {
-        String packageName = mContext.getResources().getString(
-                R.string.config_defaultModuleMetadataProvider);
-        if (TextUtils.isEmpty(packageName)) {
-            return null;
-        }
-        return packageName;
-    }
-
-    @Nullable
-    private VersionedPackage getModuleMetadataPackage() {
-        String packageName = getModuleMetadataPackageName();
-        if (packageName == null) {
-            return null;
-        }
-
+    private String getLoggingParentName(String packageName) {
+        PackageManager packageManager = mContext.getPackageManager();
         try {
-            return new VersionedPackage(packageName, mContext.getPackageManager().getPackageInfo(
-                            packageName, 0 /* flags */).getLongVersionCode());
-        } catch (PackageManager.NameNotFoundException e) {
-            Slog.w(TAG, "Module metadata provider not found");
+            ApplicationInfo ai = packageManager.getApplicationInfo(packageName,
+                    PackageManager.GET_META_DATA);
+            if (ai.metaData == null) {
+                return null;
+            }
+            return ai.metaData.getString(LOGGING_PARENT_KEY);
+        } catch (Exception e) {
+            Slog.w(TAG, "Unable to discover logging parent package: " + packageName, e);
             return null;
         }
     }
@@ -294,7 +304,7 @@
                     if (logPackage != null) {
                         // We save the rollback id so that after reboot, we can log if rollback was
                         // successful or not. If logPackage is null, then there is nothing to log.
-                        saveLastStagedRollbackId(rollbackId);
+                        saveStagedRollbackId(rollbackId);
                     }
                     logEvent(logPackage,
                             StatsLog
@@ -338,34 +348,39 @@
         }
     }
 
-    private void saveLastStagedRollbackId(int stagedRollbackId) {
+    private void saveStagedRollbackId(int stagedRollbackId) {
         try {
-            FileOutputStream fos = new FileOutputStream(mLastStagedRollbackIdFile);
+            FileOutputStream fos = new FileOutputStream(
+                    mLastStagedRollbackIdsFile, /*append*/true);
             PrintWriter pw = new PrintWriter(fos);
-            pw.println(stagedRollbackId);
+            pw.append(",").append(String.valueOf(stagedRollbackId));
             pw.flush();
             FileUtils.sync(fos);
             pw.close();
         } catch (IOException e) {
             Slog.e(TAG, "Failed to save last staged rollback id", e);
-            mLastStagedRollbackIdFile.delete();
+            mLastStagedRollbackIdsFile.delete();
         }
     }
 
-    private int popLastStagedRollbackId() {
-        int rollbackId = INVALID_ROLLBACK_ID;
-        if (!mLastStagedRollbackIdFile.exists()) {
-            return rollbackId;
+    private List<Integer> popLastStagedRollbackIds() {
+        try (BufferedReader reader =
+                     new BufferedReader(new FileReader(mLastStagedRollbackIdsFile))) {
+            String line = reader.readLine();
+            // line is of format : ",id1,id2,id3....,idn"
+            String[] sessionIdsStr = line.split(",");
+            ArrayList<Integer> result = new ArrayList<>();
+            for (String sessionIdStr: sessionIdsStr) {
+                if (!TextUtils.isEmpty(sessionIdStr.trim())) {
+                    result.add(Integer.parseInt(sessionIdStr));
+                }
+            }
+            return result;
+        } catch (Exception ignore) {
+            return Collections.emptyList();
+        } finally {
+            mLastStagedRollbackIdsFile.delete();
         }
-
-        try {
-            rollbackId = Integer.parseInt(
-                    IoUtils.readFileAsString(mLastStagedRollbackIdFile.getAbsolutePath()).trim());
-        } catch (IOException | NumberFormatException e) {
-            Slog.e(TAG, "Failed to retrieve last staged rollback id", e);
-        }
-        mLastStagedRollbackIdFile.delete();
-        return rollbackId;
     }
 
     private static String rollbackTypeToString(int type) {
@@ -383,15 +398,32 @@
         }
     }
 
-    private static void logEvent(@Nullable VersionedPackage logPackage, int type,
-            int rollbackReason, @NonNull String failingPackageName) {
-        Slog.i(TAG, "Watchdog event occurred of type: " + rollbackTypeToString(type));
-        if (logPackage != null) {
-            StatsLog.logWatchdogRollbackOccurred(type, logPackage.getPackageName(),
-                    logPackage.getVersionCode(), rollbackReason, failingPackageName);
+    private static String rollbackReasonToString(int reason) {
+        switch (reason) {
+            case StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_NATIVE_CRASH:
+                return "REASON_NATIVE_CRASH";
+            case StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_EXPLICIT_HEALTH_CHECK:
+                return "REASON_EXPLICIT_HEALTH_CHECK";
+            case StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_CRASH:
+                return "REASON_APP_CRASH";
+            case StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_NOT_RESPONDING:
+                return "REASON_APP_NOT_RESPONDING";
+            default:
+                return "UNKNOWN";
         }
     }
 
+    private static void logEvent(@Nullable VersionedPackage logPackage, int type,
+            int rollbackReason, @NonNull String failingPackageName) {
+        Slog.i(TAG, "Watchdog event occurred with type: " + rollbackTypeToString(type)
+                + " logPackage: " + logPackage
+                + " rollbackReason: " + rollbackReasonToString(rollbackReason)
+                + " failedPackageName: " + failingPackageName);
+        if (logPackage != null) {
+            StatsLog.logWatchdogRollbackOccurred(type, logPackage.getPackageName(),
+                    logPackage.getLongVersionCode(), rollbackReason, failingPackageName);
+        }
+    }
 
     /**
      * Returns true if the package name is the name of a module.
@@ -422,10 +454,21 @@
         } else {
             failedPackageToLog = failedPackage.getPackageName();
         }
-        final VersionedPackage logPackage = isModule(failedPackage.getPackageName())
-                ? getModuleMetadataPackage()
-                : null;
+        VersionedPackage logPackageTemp = null;
+        if (isModule(failedPackage.getPackageName())) {
+            String logPackageName = getLoggingParentName(failedPackage.getPackageName());
+            if (logPackageName == null) {
+                logPackageName = failedPackage.getPackageName();
+            }
+            try {
+                logPackageTemp = new VersionedPackage(logPackageName, mContext.getPackageManager()
+                        .getPackageInfo(logPackageName, 0 /* flags */).getLongVersionCode());
+            } catch (PackageManager.NameNotFoundException e) {
+                logPackageTemp = null;
+            }
+        }
 
+        final VersionedPackage logPackage = logPackageTemp;
         logEvent(logPackage,
                 StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_INITIATE,
                 reasonToLog, failedPackageToLog);
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerModule.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerModule.java
index adf16fa..372c1f5 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerModule.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerModule.java
@@ -174,7 +174,17 @@
         for (Session session : mActiveSessions) {
             session.moduleDied();
         }
+        reset();
+    }
+
+    /**
+     * Resets the transient state of this object.
+     */
+    private void reset() {
         attachToHal();
+        // We conservatively assume that external capture is active until explicitly told otherwise.
+        mRecognitionAvailable = mProperties.concurrentCapture;
+        mNumLoadedModels = 0;
     }
 
     /**
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index 3c41c10..a0e6be4 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -2274,20 +2274,104 @@
         return StatsManager.PULL_SUCCESS;
     }
 
+    private final Object mDebugElapsedClockLock = new Object();
+    private long mDebugElapsedClockPreviousValue = 0;
+    private long mDebugElapsedClockPullCount = 0;
+
     private void registerDebugElapsedClock() {
-        // No op.
+        int tagId = StatsLog.DEBUG_ELAPSED_CLOCK;
+        PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+                .setAdditiveFields(new int[] {1, 2, 3, 4})
+                .build();
+        mStatsManager.registerPullAtomCallback(
+                tagId,
+                metadata,
+                (atomTag, data) -> pullDebugElapsedClock(atomTag, data),
+                BackgroundThread.getExecutor()
+        );
     }
 
-    private void pullDebugElapsedClock() {
-        // No op.
+    private int pullDebugElapsedClock(int atomTag, List<StatsEvent> pulledData) {
+        final long elapsedMillis = SystemClock.elapsedRealtime();
+
+        synchronized (mDebugElapsedClockLock) {
+            final long clockDiffMillis = mDebugElapsedClockPreviousValue == 0
+                    ? 0 : elapsedMillis - mDebugElapsedClockPreviousValue;
+
+            StatsEvent e = StatsEvent.newBuilder()
+                    .setAtomId(atomTag)
+                    .writeLong(mDebugElapsedClockPullCount)
+                    .writeLong(elapsedMillis)
+                    // Log it twice to be able to test multi-value aggregation from ValueMetric.
+                    .writeLong(elapsedMillis)
+                    .writeLong(clockDiffMillis)
+                    .writeInt(1 /* always set */)
+                    .build();
+            pulledData.add(e);
+
+            if (mDebugElapsedClockPullCount % 2 == 1) {
+                StatsEvent e2 = StatsEvent.newBuilder()
+                        .setAtomId(atomTag)
+                        .writeLong(mDebugElapsedClockPullCount)
+                        .writeLong(elapsedMillis)
+                        // Log it twice to be able to test multi-value aggregation from ValueMetric.
+                        .writeLong(elapsedMillis)
+                        .writeLong(clockDiffMillis)
+                        .writeInt(2 /* set on odd pulls */)
+                        .build();
+                pulledData.add(e2);
+            }
+
+            mDebugElapsedClockPullCount++;
+            mDebugElapsedClockPreviousValue = elapsedMillis;
+        }
+
+        return StatsManager.PULL_SUCCESS;
     }
 
+    private final Object mDebugFailingElapsedClockLock = new Object();
+    private long mDebugFailingElapsedClockPreviousValue = 0;
+    private long mDebugFailingElapsedClockPullCount = 0;
+
     private void registerDebugFailingElapsedClock() {
-        // No op.
+        int tagId = StatsLog.DEBUG_FAILING_ELAPSED_CLOCK;
+        PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+                .setAdditiveFields(new int[] {1, 2, 3, 4})
+                .build();
+        mStatsManager.registerPullAtomCallback(
+                tagId,
+                metadata,
+                (atomTag, data) -> pullDebugFailingElapsedClock(atomTag, data),
+                BackgroundThread.getExecutor()
+        );
     }
 
-    private void pullDebugFailingElapsedClock() {
-        // No op.
+    private int pullDebugFailingElapsedClock(int atomTag, List<StatsEvent> pulledData) {
+        final long elapsedMillis = SystemClock.elapsedRealtime();
+
+        synchronized (mDebugFailingElapsedClockLock) {
+            // Fails every 5 buckets.
+            if (mDebugFailingElapsedClockPullCount++ % 5 == 0) {
+                mDebugFailingElapsedClockPreviousValue = elapsedMillis;
+                Slog.e(TAG, "Failing debug elapsed clock");
+                return StatsManager.PULL_SKIP;
+            }
+
+            StatsEvent e = StatsEvent.newBuilder()
+                    .setAtomId(atomTag)
+                    .writeLong(mDebugFailingElapsedClockPullCount)
+                    .writeLong(elapsedMillis)
+                    // Log it twice to be able to test multi-value aggregation from ValueMetric.
+                    .writeLong(elapsedMillis)
+                    .writeLong(mDebugFailingElapsedClockPreviousValue == 0
+                            ? 0 : elapsedMillis - mDebugFailingElapsedClockPreviousValue)
+                    .build();
+            pulledData.add(e);
+
+            mDebugFailingElapsedClockPreviousValue = elapsedMillis;
+        }
+
+        return StatsManager.PULL_SUCCESS;
     }
 
     private void registerBuildInformation() {
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index 6ea274d..8f71943 100755
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -44,6 +44,7 @@
 import android.media.tv.ITvInputHardwareCallback;
 import android.media.tv.TvInputHardwareInfo;
 import android.media.tv.TvInputInfo;
+import android.media.tv.TvInputService.PriorityHintUseCaseType;
 import android.media.tv.TvStreamConfig;
 import android.os.Handler;
 import android.os.IBinder;
@@ -363,7 +364,8 @@
      * release is notified via ITvInputHardwareCallback.onReleased().
      */
     public ITvInputHardware acquireHardware(int deviceId, ITvInputHardwareCallback callback,
-            TvInputInfo info, int callingUid, int resolvedUserId) {
+            TvInputInfo info, int callingUid, int resolvedUserId,
+            String tvInputSessionId, @PriorityHintUseCaseType int priorityHint) {
         if (callback == null) {
             throw new NullPointerException();
         }
@@ -373,6 +375,8 @@
                 Slog.e(TAG, "Invalid deviceId : " + deviceId);
                 return null;
             }
+            // TODO: check with TRM to compare the client's priority with the current holder's
+            // priority. If lower, do nothing.
             if (checkUidChangedLocked(connection, callingUid, resolvedUserId)) {
                 TvInputHardwareImpl hardware =
                         new TvInputHardwareImpl(connection.getHardwareInfoLocked());
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index eb7c5ca..e8704ab 100755
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -1736,8 +1736,9 @@
 
         @Override
         public ITvInputHardware acquireTvInputHardware(int deviceId,
-                ITvInputHardwareCallback callback, TvInputInfo info, int userId)
-                throws RemoteException {
+                ITvInputHardwareCallback callback, TvInputInfo info, int userId,
+                String tvInputSessionId,
+                @TvInputService.PriorityHintUseCaseType int priorityHint) throws RemoteException {
             if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE)
                     != PackageManager.PERMISSION_GRANTED) {
                 return null;
@@ -1749,7 +1750,8 @@
                     userId, "acquireTvInputHardware");
             try {
                 return mTvInputHardwareManager.acquireHardware(
-                        deviceId, callback, info, callingUid, resolvedUserId);
+                        deviceId, callback, info, callingUid, resolvedUserId,
+                        tvInputSessionId, priorityHint);
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 2c325e5..4f1d40e 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -1958,7 +1958,7 @@
             }
         } else if (type == TYPE_WALLPAPER) {
             layoutWallpaper(displayFrames, pf, df, cf);
-        } else if (win == mStatusBar) {
+        } else if (win == mStatusBar || type == TYPE_NOTIFICATION_SHADE) {
             df.set(displayFrames.mUnrestricted);
             pf.set(displayFrames.mUnrestricted);
             cf.set(displayFrames.mStable);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index e939d84..7830c60 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -156,6 +156,7 @@
 import android.content.PermissionChecker;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.CrossProfileApps;
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageInfo;
@@ -302,6 +303,7 @@
 import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -310,6 +312,7 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Function;
+import java.util.stream.Collectors;
 
 /**
  * Implementation of the device policy APIs.
@@ -370,6 +373,8 @@
 
     private static final String TAG_PROTECTED_PACKAGES = "protected-packages";
 
+    private static final String TAG_SECONDARY_LOCK_SCREEN = "secondary-lock-screen";
+
     private static final int REQUEST_EXPIRE_PASSWORD = 5571;
 
     private static final long MS_PER_DAY = TimeUnit.DAYS.toMillis(1);
@@ -522,11 +527,11 @@
     /**
      * For admin apps targeting R+, throw when the app sets password requirement
      * that is not taken into account at given quality. For example when quality is set
-     * to {@link DevicePolicyManager#PASSWORD_QUALITY_UNSPECIFIED}, it doesn't make sense to
-     * require certain password length. If the intent is to require a password of certain length
-     * having at least NUMERIC quality, the admin should first call
-     * {@link #setPasswordQuality(ComponentName, int, boolean)} and only then call
-     * {@link #setPasswordMinimumLength(ComponentName, int, boolean)}.
+     * to {@link android.app.admin.DevicePolicyManager#PASSWORD_QUALITY_UNSPECIFIED}, it doesn't
+     * make sense to require certain password length. If the intent is to require a password of
+     * certain length having at least NUMERIC quality, the admin should first call
+     * {@link android.app.admin.DevicePolicyManager#setPasswordQuality} and only then call
+     * {@link android.app.admin.DevicePolicyManager#setPasswordMinimumLength}.
      *
      * <p>Conversely when an admin app targeting R+ lowers password quality, those
      * requirements that stop making sense are reset to default values.
@@ -771,6 +776,8 @@
 
         boolean mCurrentInputMethodSet = false;
 
+        boolean mSecondaryLockscreenEnabled = false;
+
         // TODO(b/35385311): Keep track of metadata in TrustedCertificateStore instead.
         Set<String> mOwnerInstalledCaCerts = new ArraySet<>();
 
@@ -3322,6 +3329,12 @@
                 out.endTag(null, TAG_LOCK_TASK_FEATURES);
             }
 
+            if (policy.mSecondaryLockscreenEnabled) {
+                out.startTag(null, TAG_SECONDARY_LOCK_SCREEN);
+                out.attribute(null, ATTR_VALUE, Boolean.toString(true));
+                out.endTag(null, TAG_SECONDARY_LOCK_SCREEN);
+            }
+
             if (policy.mStatusBarDisabled) {
                 out.startTag(null, TAG_STATUS_BAR);
                 out.attribute(null, ATTR_DISABLED, Boolean.toString(policy.mStatusBarDisabled));
@@ -3571,6 +3584,9 @@
                 } else if (TAG_LOCK_TASK_FEATURES.equals(tag)) {
                     policy.mLockTaskFeatures = Integer.parseInt(
                             parser.getAttributeValue(null, ATTR_VALUE));
+                } else if (TAG_SECONDARY_LOCK_SCREEN.equals(tag)) {
+                    policy.mSecondaryLockscreenEnabled = Boolean.parseBoolean(
+                            parser.getAttributeValue(null, ATTR_VALUE));
                 } else if (TAG_STATUS_BAR.equals(tag)) {
                     policy.mStatusBarDisabled = Boolean.parseBoolean(
                             parser.getAttributeValue(null, ATTR_DISABLED));
@@ -8601,6 +8617,7 @@
         // Clear delegations.
         policy.mDelegationMap.clear();
         policy.mStatusBarDisabled = false;
+        policy.mSecondaryLockscreenEnabled = false;
         policy.mUserProvisioningState = DevicePolicyManager.STATE_USER_UNMANAGED;
         policy.mAffiliationIds.clear();
         policy.mLockTaskPackages.clear();
@@ -11154,6 +11171,33 @@
     }
 
     @Override
+    public void setSecondaryLockscreenEnabled(ComponentName who, boolean enabled) {
+        enforceCanSetSecondaryLockscreenEnabled(who);
+        synchronized (getLockObject()) {
+            final int userId = mInjector.userHandleGetCallingUserId();
+            DevicePolicyData policy = getUserData(userId);
+            policy.mSecondaryLockscreenEnabled = enabled;
+            saveSettingsLocked(userId);
+        }
+    }
+
+    @Override
+    public boolean isSecondaryLockscreenEnabled(int userId) {
+        synchronized (getLockObject()) {
+            return getUserData(userId).mSecondaryLockscreenEnabled;
+        }
+    }
+
+    private void enforceCanSetSecondaryLockscreenEnabled(ComponentName who) {
+        enforceProfileOrDeviceOwner(who);
+        final int userId = mInjector.userHandleGetCallingUserId();
+        if (isManagedProfile(userId)) {
+            throw new SecurityException(
+                    "User " + userId + " is not allowed to call setSecondaryLockscreenEnabled");
+        }
+    }
+
+    @Override
     public void setLockTaskPackages(ComponentName who, String[] packages)
             throws SecurityException {
         Objects.requireNonNull(who, "ComponentName is null");
@@ -14846,12 +14890,18 @@
         }
         Objects.requireNonNull(who, "ComponentName is null");
         Objects.requireNonNull(packageNames, "Package names is null");
+        final List<String> previousCrossProfilePackages;
         synchronized (getLockObject()) {
             final ActiveAdmin admin =
                     getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            previousCrossProfilePackages = admin.mCrossProfilePackages;
             admin.mCrossProfilePackages = packageNames;
             saveSettingsLocked(mInjector.userHandleGetCallingUserId());
         }
+        final CrossProfileApps crossProfileApps = mContext.getSystemService(CrossProfileApps.class);
+        mInjector.binderWithCleanCallingIdentity(
+                () -> crossProfileApps.resetInteractAcrossProfilesAppOps(
+                        previousCrossProfilePackages, new HashSet<>(packageNames)));
     }
 
     @Override
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 0b7c359..258d762 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -223,14 +223,8 @@
             "com.android.server.usb.UsbService$Lifecycle";
     private static final String MIDI_SERVICE_CLASS =
             "com.android.server.midi.MidiService$Lifecycle";
-    private static final String WIFI_APEX_SERVICE_JAR_PATH =
-            "/apex/com.android.wifi/javalib/wifi-service.jar";
     private static final String WIFI_SERVICE_CLASS =
             "com.android.server.wifi.WifiService";
-    private static final String WIFI_SCANNING_SERVICE_CLASS =
-            "com.android.server.wifi.scanner.WifiScanningService";
-    private static final String WIFI_RTT_SERVICE_CLASS =
-            "com.android.server.wifi.rtt.RttService";
     private static final String WIFI_AWARE_SERVICE_CLASS =
             "com.android.server.wifi.aware.WifiAwareService";
     private static final String WIFI_P2P_SERVICE_CLASS =
@@ -1437,36 +1431,33 @@
                     PackageManager.FEATURE_WIFI)) {
                 // Wifi Service must be started first for wifi-related services.
                 t.traceBegin("StartWifi");
-                mSystemServiceManager.startServiceFromJar(
-                        WIFI_SERVICE_CLASS, WIFI_APEX_SERVICE_JAR_PATH);
+                mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
                 t.traceEnd();
                 t.traceBegin("StartWifiScanning");
-                mSystemServiceManager.startServiceFromJar(
-                        WIFI_SCANNING_SERVICE_CLASS, WIFI_APEX_SERVICE_JAR_PATH);
+                mSystemServiceManager.startService(
+                        "com.android.server.wifi.scanner.WifiScanningService");
                 t.traceEnd();
             }
 
             if (context.getPackageManager().hasSystemFeature(
                     PackageManager.FEATURE_WIFI_RTT)) {
                 t.traceBegin("StartRttService");
-                mSystemServiceManager.startServiceFromJar(
-                        WIFI_RTT_SERVICE_CLASS, WIFI_APEX_SERVICE_JAR_PATH);
+                mSystemServiceManager.startService(
+                        "com.android.server.wifi.rtt.RttService");
                 t.traceEnd();
             }
 
             if (context.getPackageManager().hasSystemFeature(
                     PackageManager.FEATURE_WIFI_AWARE)) {
                 t.traceBegin("StartWifiAware");
-                mSystemServiceManager.startServiceFromJar(
-                        WIFI_AWARE_SERVICE_CLASS, WIFI_APEX_SERVICE_JAR_PATH);
+                mSystemServiceManager.startService(WIFI_AWARE_SERVICE_CLASS);
                 t.traceEnd();
             }
 
             if (context.getPackageManager().hasSystemFeature(
                     PackageManager.FEATURE_WIFI_DIRECT)) {
                 t.traceBegin("StartWifiP2P");
-                mSystemServiceManager.startServiceFromJar(
-                        WIFI_P2P_SERVICE_CLASS, WIFI_APEX_SERVICE_JAR_PATH);
+                mSystemServiceManager.startService(WIFI_P2P_SERVICE_CLASS);
                 t.traceEnd();
             }
 
diff --git a/services/net/Android.bp b/services/net/Android.bp
index cf84bdf..dbc2df8 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -16,6 +16,7 @@
         "netd_aidl_interface-unstable-java",
         "netlink-client",
         "networkstack-client",
+        "net-utils-services-common",
     ],
 }
 
diff --git a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
index 96ff9c1..1a7b1d3 100644
--- a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
+++ b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
@@ -18,6 +18,8 @@
 
 import static android.app.AppOpsManager.MODE_ALLOWED;
 import static android.app.AppOpsManager.OP_INTERACT_ACROSS_PROFILES;
+import static android.content.Intent.FLAG_RECEIVER_FOREGROUND;
+import static android.content.Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND;
 import static android.content.Intent.FLAG_RECEIVER_REGISTERED_ONLY;
 import static android.content.pm.CrossProfileApps.ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED;
 
@@ -37,11 +39,13 @@
 import android.app.admin.DevicePolicyManagerInternal;
 import android.content.ContextWrapper;
 import android.content.Intent;
+import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
+import android.content.pm.ResolveInfo;
 import android.content.pm.parsing.AndroidPackage;
 import android.content.pm.parsing.PackageImpl;
 import android.os.Process;
@@ -70,6 +74,7 @@
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -106,6 +111,7 @@
         MockitoAnnotations.initMocks(this);
         mockCrossProfileAppInstalledAndEnabledOnEachProfile();
         mockCrossProfileAppRequestsInteractAcrossProfiles();
+        mockCrossProfileAppRegistersBroadcastReceiver();
         mockCrossProfileAppWhitelisted();
     }
 
@@ -113,19 +119,21 @@
         // They are enabled by default, so we simply have to ensure that a package info with an
         // application info is returned.
         final PackageInfo packageInfo = buildTestPackageInfo();
+        mockCrossProfileAppInstalledOnProfile(
+                packageInfo, PERSONAL_PROFILE_USER_ID, PERSONAL_PROFILE_UID);
+        mockCrossProfileAppInstalledOnProfile(packageInfo, WORK_PROFILE_USER_ID, WORK_PROFILE_UID);
+    }
+
+    private void mockCrossProfileAppInstalledOnProfile(
+            PackageInfo packageInfo, @UserIdInt int userId, int uid) {
         when(mPackageManagerInternal.getPackageInfo(
                         eq(CROSS_PROFILE_APP_PACKAGE_NAME),
                         /* flags= */ anyInt(),
                         /* filterCallingUid= */ anyInt(),
-                        eq(PERSONAL_PROFILE_USER_ID)))
+                        eq(userId)))
                 .thenReturn(packageInfo);
-        when(mPackageManagerInternal.getPackageInfo(
-                        eq(CROSS_PROFILE_APP_PACKAGE_NAME),
-                        /* flags= */ anyInt(),
-                        /* filterCallingUid= */ anyInt(),
-                        eq(WORK_PROFILE_USER_ID)))
-                .thenReturn(packageInfo);
-        mockCrossProfileAndroidPackage(PackageImpl.forParsing(CROSS_PROFILE_APP_PACKAGE_NAME));
+        when(mPackageManagerInternal.getPackage(uid))
+                .thenReturn(PackageImpl.forParsing(CROSS_PROFILE_APP_PACKAGE_NAME));
     }
 
     private PackageInfo buildTestPackageInfo() {
@@ -140,6 +148,31 @@
                 .thenReturn(new String[] {CROSS_PROFILE_APP_PACKAGE_NAME});
     }
 
+    private void mockCrossProfileAppRegistersBroadcastReceiver() {
+        final ShadowApplicationPackageManager shadowApplicationPackageManager =
+                Shadow.extract(mPackageManager);
+        final Intent baseIntent =
+                new Intent(ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED)
+                        .setPackage(CROSS_PROFILE_APP_PACKAGE_NAME);
+        final Intent manifestIntent =
+                new Intent(baseIntent)
+                        .setFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
+                                | Intent.FLAG_RECEIVER_FOREGROUND);
+        final Intent registeredIntent =
+                new Intent(baseIntent).setFlags(FLAG_RECEIVER_REGISTERED_ONLY);
+        final List<ResolveInfo> resolveInfos = Lists.newArrayList(buildTestResolveInfo());
+        shadowApplicationPackageManager.setResolveInfosForIntent(manifestIntent, resolveInfos);
+        shadowApplicationPackageManager.setResolveInfosForIntent(registeredIntent, resolveInfos);
+    }
+
+    private ResolveInfo buildTestResolveInfo() {
+        final ResolveInfo resolveInfo = new ResolveInfo();
+        resolveInfo.activityInfo = new ActivityInfo();
+        resolveInfo.activityInfo.packageName = CROSS_PROFILE_APP_PACKAGE_NAME;
+        resolveInfo.activityInfo.name = CROSS_PROFILE_APP_PACKAGE_NAME + ".Receiver";
+        return resolveInfo;
+    }
+
     private void mockCrossProfileAppWhitelisted() {
         when(mDevicePolicyManagerInternal.getAllCrossProfilePackages())
                 .thenReturn(Lists.newArrayList(CROSS_PROFILE_APP_PACKAGE_NAME));
@@ -191,16 +224,6 @@
     }
 
     @Test
-    public void setInteractAcrossProfilesAppOp_missingManageAppOpsModes_throwsSecurityException() {
-        denyPermissions(Manifest.permission.MANAGE_APP_OPS_MODES);
-        try {
-            mCrossProfileAppsServiceImpl.setInteractAcrossProfilesAppOp(
-                    CROSS_PROFILE_APP_PACKAGE_NAME, MODE_ALLOWED);
-            fail();
-        } catch (SecurityException expected) {}
-    }
-
-    @Test
     public void setInteractAcrossProfilesAppOp_setsAppOp() {
         mCrossProfileAppsServiceImpl.setInteractAcrossProfilesAppOp(
                 CROSS_PROFILE_APP_PACKAGE_NAME, MODE_ALLOWED);
@@ -294,6 +317,54 @@
         assertThat(receivedManifestCanInteractAcrossProfilesChangedBroadcast()).isTrue();
     }
 
+    @Test
+    public void canConfigureInteractAcrossProfiles_packageNotInstalledInProfile_returnsFalse() {
+        mockUninstallCrossProfileAppFromWorkProfile();
+        assertThat(mCrossProfileAppsServiceImpl
+                .canConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME))
+                .isFalse();
+    }
+
+    private void mockUninstallCrossProfileAppFromWorkProfile() {
+        when(mPackageManagerInternal.getPackageInfo(
+                        eq(CROSS_PROFILE_APP_PACKAGE_NAME),
+                        /* flags= */ anyInt(),
+                        /* filterCallingUid= */ anyInt(),
+                        eq(WORK_PROFILE_USER_ID)))
+                .thenReturn(null);
+        when(mPackageManagerInternal.getPackage(WORK_PROFILE_UID)).thenReturn(null);
+    }
+
+    @Test
+    public void canConfigureInteractAcrossProfiles_packageDoesNotRequestInteractAcrossProfiles_returnsFalse()
+            throws Exception {
+        mockCrossProfileAppDoesNotRequestInteractAcrossProfiles();
+        assertThat(mCrossProfileAppsServiceImpl
+                .canConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME))
+                .isFalse();
+    }
+
+    private void mockCrossProfileAppDoesNotRequestInteractAcrossProfiles() throws Exception {
+        final String permissionName = Manifest.permission.INTERACT_ACROSS_PROFILES;
+        when(mIPackageManager.getAppOpPermissionPackages(permissionName))
+                .thenReturn(new String[] {});
+    }
+
+    @Test
+    public void canConfigureInteractAcrossProfiles_packageNotWhitelisted_returnsFalse() {
+        mockCrossProfileAppNotWhitelisted();
+        assertThat(mCrossProfileAppsServiceImpl
+                .canConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME))
+                .isFalse();
+    }
+
+    @Test
+    public void canConfigureInteractAcrossProfiles_returnsTrue() {
+        assertThat(mCrossProfileAppsServiceImpl
+                .canConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME))
+                .isTrue();
+    }
+
     private void explicitlySetInteractAcrossProfilesAppOp(@Mode int mode) {
         explicitlySetInteractAcrossProfilesAppOp(PERSONAL_PROFILE_UID, mode);
     }
@@ -311,7 +382,6 @@
         shadowOf(mContext).denyPermissions(Process.myPid(), CALLING_UID, permissions);
     }
 
-
     private @Mode int getCrossProfileAppOp() {
         return getCrossProfileAppOp(PERSONAL_PROFILE_UID);
     }
@@ -365,10 +435,12 @@
     }
 
     private boolean isBroadcastManifestCanInteractAcrossProfilesChanged(Intent intent) {
-        // The manifest check is negative since the FLAG_RECEIVER_REGISTERED_ONLY flag means that
-        // manifest receivers can NOT receive the broadcast.
         return isBroadcastCanInteractAcrossProfilesChanged(intent)
-                && (intent.getFlags() & FLAG_RECEIVER_REGISTERED_ONLY) == 0;
+                && (intent.getFlags() & FLAG_RECEIVER_REGISTERED_ONLY) == 0
+                && (intent.getFlags() & FLAG_RECEIVER_INCLUDE_BACKGROUND) != 0
+                && (intent.getFlags() & FLAG_RECEIVER_FOREGROUND) != 0
+                && intent.getComponent() != null
+                && intent.getComponent().getPackageName().equals(CROSS_PROFILE_APP_PACKAGE_NAME);
     }
 
     private void declareCrossProfileAttributeOnCrossProfileApp(boolean value) {
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowApplicationPackageManager.java b/services/robotests/src/com/android/server/testing/shadows/ShadowApplicationPackageManager.java
index 1443eab..aea36e5 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowApplicationPackageManager.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowApplicationPackageManager.java
@@ -19,7 +19,10 @@
 import static android.content.pm.PackageManager.NameNotFoundException;
 
 import android.app.ApplicationPackageManager;
+import android.content.Intent;
 import android.content.pm.PackageInfo;
+import android.content.pm.ResolveInfo;
+import android.os.UserHandle;
 import android.util.ArrayMap;
 
 import org.robolectric.annotation.Implements;
@@ -100,6 +103,13 @@
         return sPackageUids.get(packageName);
     }
 
+    @Override
+    protected List<ResolveInfo> queryBroadcastReceiversAsUser(
+            Intent intent, int flags, UserHandle userHandle) {
+        // Currently does not handle multi-user.
+        return queryBroadcastReceivers(intent, flags);
+    }
+
     /** Clear package state. */
     @Resetter
     public static void reset() {
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 710e8df..d2ddff3 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -74,6 +74,8 @@
     <uses-permission android:name="android.permission.BLUETOOTH"/>
     <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
     <uses-permission android:name="android.permission.DUMP" />
+    <uses-permission android:name="android.permission.READ_DREAM_STATE"/>
+    <uses-permission android:name="android.permission.WRITE_DREAM_STATE"/>
 
     <!-- Uses API introduced in O (26) -->
     <uses-sdk android:minSdkVersion="1"
diff --git a/services/tests/servicestests/src/com/android/server/BluetoothAirplaneModeListenerTest.java b/services/tests/servicestests/src/com/android/server/BluetoothAirplaneModeListenerTest.java
new file mode 100644
index 0000000..968a402
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/BluetoothAirplaneModeListenerTest.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2019 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.server;
+
+import static org.mockito.Mockito.*;
+
+import android.bluetooth.BluetoothAdapter;
+import android.content.Context;
+import android.os.Looper;
+import android.provider.Settings;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.BluetoothAirplaneModeListener.AirplaneModeHelper;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class BluetoothAirplaneModeListenerTest {
+    private Context mContext;
+    private BluetoothAirplaneModeListener mBluetoothAirplaneModeListener;
+    private BluetoothAdapter mBluetoothAdapter;
+    private AirplaneModeHelper mHelper;
+
+    @Mock BluetoothManagerService mBluetoothManagerService;
+
+    @Before
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getTargetContext();
+
+        mHelper = mock(AirplaneModeHelper.class);
+        when(mHelper.getSettingsInt(BluetoothAirplaneModeListener.TOAST_COUNT))
+                .thenReturn(BluetoothAirplaneModeListener.MAX_TOAST_COUNT);
+        doNothing().when(mHelper).setSettingsInt(anyString(), anyInt());
+        doNothing().when(mHelper).showToastMessage();
+        doNothing().when(mHelper).onAirplaneModeChanged(any(BluetoothManagerService.class));
+
+        mBluetoothAirplaneModeListener = new BluetoothAirplaneModeListener(
+                    mBluetoothManagerService, Looper.getMainLooper(), mContext);
+        mBluetoothAirplaneModeListener.start(mHelper);
+    }
+
+    @Test
+    public void testIgnoreOnAirplanModeChange() {
+        Assert.assertFalse(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange());
+
+        when(mHelper.isBluetoothOn()).thenReturn(true);
+        Assert.assertFalse(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange());
+
+        when(mHelper.isA2dpOrHearingAidConnected()).thenReturn(true);
+        Assert.assertFalse(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange());
+
+        when(mHelper.isAirplaneModeOn()).thenReturn(true);
+        Assert.assertTrue(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange());
+    }
+
+    @Test
+    public void testHandleAirplaneModeChange_InvokeAirplaneModeChanged() {
+        mBluetoothAirplaneModeListener.handleAirplaneModeChange();
+        verify(mHelper).onAirplaneModeChanged(mBluetoothManagerService);
+    }
+
+    @Test
+    public void testHandleAirplaneModeChange_NotInvokeAirplaneModeChanged_NotPopToast() {
+        mBluetoothAirplaneModeListener.mToastCount = BluetoothAirplaneModeListener.MAX_TOAST_COUNT;
+        when(mHelper.isBluetoothOn()).thenReturn(true);
+        when(mHelper.isA2dpOrHearingAidConnected()).thenReturn(true);
+        when(mHelper.isAirplaneModeOn()).thenReturn(true);
+        mBluetoothAirplaneModeListener.handleAirplaneModeChange();
+
+        verify(mHelper).setSettingsInt(Settings.Global.BLUETOOTH_ON,
+                BluetoothManagerService.BLUETOOTH_ON_AIRPLANE);
+        verify(mHelper, times(0)).showToastMessage();
+        verify(mHelper, times(0)).onAirplaneModeChanged(mBluetoothManagerService);
+    }
+
+    @Test
+    public void testHandleAirplaneModeChange_NotInvokeAirplaneModeChanged_PopToast() {
+        mBluetoothAirplaneModeListener.mToastCount = 0;
+        when(mHelper.isBluetoothOn()).thenReturn(true);
+        when(mHelper.isA2dpOrHearingAidConnected()).thenReturn(true);
+        when(mHelper.isAirplaneModeOn()).thenReturn(true);
+        mBluetoothAirplaneModeListener.handleAirplaneModeChange();
+
+        verify(mHelper).setSettingsInt(Settings.Global.BLUETOOTH_ON,
+                BluetoothManagerService.BLUETOOTH_ON_AIRPLANE);
+        verify(mHelper).showToastMessage();
+        verify(mHelper, times(0)).onAirplaneModeChanged(mBluetoothManagerService);
+    }
+
+    @Test
+    public void testIsPopToast_PopToast() {
+        mBluetoothAirplaneModeListener.mToastCount = 0;
+        Assert.assertTrue(mBluetoothAirplaneModeListener.shouldPopToast());
+        verify(mHelper).setSettingsInt(BluetoothAirplaneModeListener.TOAST_COUNT, 1);
+    }
+
+    @Test
+    public void testIsPopToast_NotPopToast() {
+        mBluetoothAirplaneModeListener.mToastCount = BluetoothAirplaneModeListener.MAX_TOAST_COUNT;
+        Assert.assertFalse(mBluetoothAirplaneModeListener.shouldPopToast());
+        verify(mHelper, times(0)).setSettingsInt(anyString(), anyInt());
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index aeba488..8f1d0f7 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -4189,6 +4189,52 @@
                 () -> dpm.setLockTaskFeatures(admin1, flags));
     }
 
+    public void testSecondaryLockscreen_profileOwner() throws Exception {
+        mContext.binder.callingUid = DpmMockContext.CALLER_UID;
+
+        // Initial state is disabled.
+        assertFalse(dpm.isSecondaryLockscreenEnabled(DpmMockContext.CALLER_USER_HANDLE));
+
+        // Profile owner can set enabled state.
+        setAsProfileOwner(admin1);
+        dpm.setSecondaryLockscreenEnabled(admin1, true);
+        assertTrue(dpm.isSecondaryLockscreenEnabled(DpmMockContext.CALLER_USER_HANDLE));
+
+        // Managed profile managed by different package is unaffiliated - cannot set enabled.
+        final int managedProfileUserId = 15;
+        final int managedProfileAdminUid = UserHandle.getUid(managedProfileUserId, 20456);
+        final ComponentName adminDifferentPackage =
+                new ComponentName("another.package", "whatever.class");
+        addManagedProfile(adminDifferentPackage, managedProfileAdminUid, admin2);
+        mContext.binder.callingUid = managedProfileAdminUid;
+        assertExpectException(SecurityException.class, /* messageRegex= */ null,
+                () -> dpm.setSecondaryLockscreenEnabled(adminDifferentPackage, false));
+    }
+
+    public void testSecondaryLockscreen_deviceOwner() throws Exception {
+        mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+
+        // Initial state is disabled.
+        assertFalse(dpm.isSecondaryLockscreenEnabled(UserHandle.USER_SYSTEM));
+
+        // Device owners can set enabled state.
+        setupDeviceOwner();
+        dpm.setSecondaryLockscreenEnabled(admin1, true);
+        assertTrue(dpm.isSecondaryLockscreenEnabled(UserHandle.USER_SYSTEM));
+    }
+
+    public void testSecondaryLockscreen_nonOwner() throws Exception {
+        mContext.binder.callingUid = DpmMockContext.CALLER_UID;
+
+        // Initial state is disabled.
+        assertFalse(dpm.isSecondaryLockscreenEnabled(DpmMockContext.CALLER_USER_HANDLE));
+
+        // Non-DO/PO cannot set enabled state.
+        assertExpectException(SecurityException.class, /* messageRegex= */ null,
+                () -> dpm.setSecondaryLockscreenEnabled(admin1, true));
+        assertFalse(dpm.isSecondaryLockscreenEnabled(DpmMockContext.CALLER_USER_HANDLE));
+    }
+
     public void testIsDeviceManaged() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index 6cf6b67..12228c1 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -221,6 +221,8 @@
                 return mMockSystemServices.telephonyManager;
             case Context.APP_OPS_SERVICE:
                 return mMockSystemServices.appOpsManager;
+            case Context.CROSS_PROFILE_APPS_SERVICE:
+                return mMockSystemServices.crossProfileApps;
         }
         throw new UnsupportedOperationException();
     }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
index b9fb1aa..37d4081 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
@@ -42,6 +42,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.CrossProfileApps;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
@@ -120,6 +121,7 @@
     public final TimeDetector timeDetector;
     public final TimeZoneDetector timeZoneDetector;
     public final KeyChain.KeyChainConnection keyChainConnection;
+    public final CrossProfileApps crossProfileApps;
     public final PersistentDataBlockManagerInternal persistentDataBlockManagerInternal;
     public final AppOpsManager appOpsManager;
     /** Note this is a partial mock, not a real mock. */
@@ -165,6 +167,7 @@
         timeDetector = mock(TimeDetector.class);
         timeZoneDetector = mock(TimeZoneDetector.class);
         keyChainConnection = mock(KeyChain.KeyChainConnection.class, RETURNS_DEEP_STUBS);
+        crossProfileApps = mock(CrossProfileApps.class);
         persistentDataBlockManagerInternal = mock(PersistentDataBlockManagerInternal.class);
         appOpsManager = mock(AppOpsManager.class);
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
index cb9d816..7f66f3c 100644
--- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
@@ -51,7 +51,6 @@
 import org.mockito.MockitoAnnotations;
 
 import java.util.Collections;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -511,6 +510,62 @@
                 overlaySetting, 0));
     }
 
+    @Test
+    public void testInitiatingApp_DoesntFilter() {
+        final AppsFilter appsFilter =
+                new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+        appsFilter.onSystemReady();
+
+        PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"),
+                DUMMY_TARGET_UID);
+        PackageSetting calling = simulateAddPackage(appsFilter, pkg("com.some.other.package"),
+                DUMMY_CALLING_UID, withInstallSource(target.name, null, null, false));
+
+        assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
+    }
+
+    @Test
+    public void testUninstalledInitiatingApp_Filters() {
+        final AppsFilter appsFilter =
+                new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+        appsFilter.onSystemReady();
+
+        PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"),
+                DUMMY_TARGET_UID);
+        PackageSetting calling = simulateAddPackage(appsFilter, pkg("com.some.other.package"),
+                DUMMY_CALLING_UID, withInstallSource(target.name, null, null, true));
+
+        assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
+    }
+
+    @Test
+    public void testOriginatingApp_Filters() {
+        final AppsFilter appsFilter =
+                new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+        appsFilter.onSystemReady();
+
+        PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"),
+                DUMMY_TARGET_UID);
+        PackageSetting calling = simulateAddPackage(appsFilter, pkg("com.some.other.package"),
+                DUMMY_CALLING_UID, withInstallSource(null, target.name, null, false));
+
+        assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
+    }
+
+    @Test
+    public void testInstallingApp_DoesntFilter() {
+        final AppsFilter appsFilter =
+                new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+        appsFilter.onSystemReady();
+
+        PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"),
+                DUMMY_TARGET_UID);
+        PackageSetting calling = simulateAddPackage(appsFilter, pkg("com.some.other.package"),
+                DUMMY_CALLING_UID, withInstallSource(null, null, target.name, false));
+
+        assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
+    }
+
     private interface WithSettingBuilder {
         PackageSettingBuilder withBuilder(PackageSettingBuilder builder);
     }
@@ -538,5 +593,13 @@
         return setting;
     }
 
+    private WithSettingBuilder withInstallSource(String initiatingPackageName,
+            String originatingPackageName, String installerPackageName,
+            boolean isInitiatingPackageUninstalled) {
+        final InstallSource installSource = InstallSource.create(initiatingPackageName,
+                originatingPackageName, installerPackageName,
+                /* isOrphaned= */ false, isInitiatingPackageUninstalled);
+        return setting -> setting.setInstallSource(installSource);
+    }
 }
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/ModuleInfoProviderTest.java b/services/tests/servicestests/src/com/android/server/pm/ModuleInfoProviderTest.java
index 3852b9f..6a9ef8a 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ModuleInfoProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ModuleInfoProviderTest.java
@@ -15,6 +15,9 @@
  */
 package com.android.server.pm;
 
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+
 import android.content.Context;
 import android.content.pm.ModuleInfo;
 import android.content.pm.PackageManager;
@@ -22,11 +25,25 @@
 
 import com.android.frameworks.servicestests.R;
 
+import org.mockito.Mock;
+
 import java.util.Collections;
 import java.util.List;
 
 public class ModuleInfoProviderTest extends InstrumentationTestCase {
+
+    @Mock private ApexManager mApexManager;
+
+    public void setUp() {
+        initMocks(this);
+    }
+
     public void testSuccessfulParse() {
+        when(mApexManager.getApexModuleNameForPackageName("com.android.module1"))
+                .thenReturn("com.module1.apex");
+        when(mApexManager.getApexModuleNameForPackageName("com.android.module2"))
+                .thenReturn("com.module2.apex");
+
         ModuleInfoProvider provider = getProvider(R.xml.well_formed_metadata);
 
         List<ModuleInfo> mi = provider.getInstalledModules(PackageManager.MATCH_ALL);
@@ -40,11 +57,13 @@
         ModuleInfo mi1 = provider.getModuleInfo("com.android.module1", 0);
         assertEquals("com.android.module1", mi1.getPackageName());
         assertEquals("module_1_name", mi1.getName());
+        assertEquals("com.module1.apex", mi1.getApexModuleName());
         assertEquals(false, mi1.isHidden());
 
         ModuleInfo mi2 = provider.getModuleInfo("com.android.module2", 0);
         assertEquals("com.android.module2", mi2.getPackageName());
         assertEquals("module_2_name", mi2.getName());
+        assertEquals("com.module2.apex", mi2.getApexModuleName());
         assertEquals(true, mi2.isHidden());
     }
 
@@ -75,6 +94,7 @@
      */
     private ModuleInfoProvider getProvider(int resourceId) {
         final Context ctx = getInstrumentation().getContext();
-        return new ModuleInfoProvider(ctx.getResources().getXml(resourceId), ctx.getResources());
+        return new ModuleInfoProvider(
+                ctx.getResources().getXml(resourceId), ctx.getResources(), mApexManager);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java b/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
index 2473997..8441494 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
@@ -41,6 +41,7 @@
     private SparseArray<PackageUserState> mUserStates = new SparseArray<>();
     private AndroidPackage mPkg;
     private int mAppId;
+    private InstallSource mInstallSource;
 
     public PackageSettingBuilder setPackage(AndroidPackage pkg) {
         this.mPkg = pkg;
@@ -137,6 +138,11 @@
         return this;
     }
 
+    public PackageSettingBuilder setInstallSource(InstallSource installSource) {
+        mInstallSource = installSource;
+        return this;
+    }
+
     public PackageSetting build() {
         final PackageSetting packageSetting = new PackageSetting(mName, mRealName,
                 new File(mCodePath), new File(mResourcePath),
@@ -146,6 +152,9 @@
         packageSetting.pkg = mPkg;
         packageSetting.appId = mAppId;
         packageSetting.volumeUuid = this.mVolumeUuid;
+        if (mInstallSource != null) {
+            packageSetting.installSource = mInstallSource;
+        }
         for (int i = 0; i < mUserStates.size(); i++) {
             packageSetting.setUserState(mUserStates.keyAt(i), mUserStates.valueAt(i));
         }
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index 25cef56..6eef41a 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -806,4 +806,173 @@
         assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
                 DisplayPowerRequest.POLICY_BRIGHT);
     }
+
+    @Test
+    public void testIsAmbientDisplayAvailable_available() throws Exception {
+        createService();
+        when(mAmbientDisplayConfigurationMock.ambientDisplayAvailable()).thenReturn(true);
+
+        assertThat(mService.getBinderServiceInstance().isAmbientDisplayAvailable()).isTrue();
+    }
+
+    @Test
+    public void testIsAmbientDisplayAvailable_unavailable() throws Exception {
+        createService();
+        when(mAmbientDisplayConfigurationMock.ambientDisplayAvailable()).thenReturn(false);
+
+        assertThat(mService.getBinderServiceInstance().isAmbientDisplayAvailable()).isFalse();
+    }
+
+    @Test
+    public void testSuppressAmbientDisplay_suppressed() throws Exception {
+        createService();
+        mService.getBinderServiceInstance().suppressAmbientDisplay("test", true);
+
+        assertThat(Settings.Secure.getInt(mContextSpy.getContentResolver(),
+            Settings.Secure.SUPPRESS_DOZE)).isEqualTo(1);
+    }
+
+    @Test
+    public void testSuppressAmbientDisplay_multipleCallers_suppressed() throws Exception {
+        createService();
+        mService.getBinderServiceInstance().suppressAmbientDisplay("test1", true);
+        mService.getBinderServiceInstance().suppressAmbientDisplay("test2", false);
+
+        assertThat(Settings.Secure.getInt(mContextSpy.getContentResolver(),
+            Settings.Secure.SUPPRESS_DOZE)).isEqualTo(1);
+    }
+
+    @Test
+    public void testSuppressAmbientDisplay_suppressTwice_suppressed() throws Exception {
+        createService();
+        mService.getBinderServiceInstance().suppressAmbientDisplay("test", true);
+        mService.getBinderServiceInstance().suppressAmbientDisplay("test", true);
+
+        assertThat(Settings.Secure.getInt(mContextSpy.getContentResolver(),
+            Settings.Secure.SUPPRESS_DOZE)).isEqualTo(1);
+    }
+
+    @Test
+    public void testSuppressAmbientDisplay_suppressTwiceThenUnsuppress_notSuppressed()
+            throws Exception {
+        createService();
+        mService.getBinderServiceInstance().suppressAmbientDisplay("test", true);
+        mService.getBinderServiceInstance().suppressAmbientDisplay("test", true);
+        mService.getBinderServiceInstance().suppressAmbientDisplay("test", false);
+
+        assertThat(Settings.Secure.getInt(mContextSpy.getContentResolver(),
+            Settings.Secure.SUPPRESS_DOZE)).isEqualTo(0);
+    }
+
+    @Test
+    public void testSuppressAmbientDisplay_notSuppressed() throws Exception {
+        createService();
+        mService.getBinderServiceInstance().suppressAmbientDisplay("test", false);
+
+        assertThat(Settings.Secure.getInt(mContextSpy.getContentResolver(),
+            Settings.Secure.SUPPRESS_DOZE)).isEqualTo(0);
+    }
+
+    @Test
+    public void testSuppressAmbientDisplay_unsuppressTwice_notSuppressed() throws Exception {
+        createService();
+        mService.getBinderServiceInstance().suppressAmbientDisplay("test", false);
+        mService.getBinderServiceInstance().suppressAmbientDisplay("test", false);
+
+        assertThat(Settings.Secure.getInt(mContextSpy.getContentResolver(),
+            Settings.Secure.SUPPRESS_DOZE)).isEqualTo(0);
+    }
+
+    @Test
+    public void testIsAmbientDisplaySuppressed_default_notSuppressed() throws Exception {
+        createService();
+
+        assertThat(mService.getBinderServiceInstance().isAmbientDisplaySuppressed()).isFalse();
+    }
+
+    @Test
+    public void testIsAmbientDisplaySuppressed_suppressed() throws Exception {
+        createService();
+        mService.getBinderServiceInstance().suppressAmbientDisplay("test", true);
+
+        assertThat(mService.getBinderServiceInstance().isAmbientDisplaySuppressed()).isTrue();
+    }
+
+    @Test
+    public void testIsAmbientDisplaySuppressed_notSuppressed() throws Exception {
+        createService();
+        mService.getBinderServiceInstance().suppressAmbientDisplay("test", false);
+
+        assertThat(mService.getBinderServiceInstance().isAmbientDisplaySuppressed()).isFalse();
+    }
+
+    @Test
+    public void testIsAmbientDisplaySuppressed_multipleTokens_suppressed() throws Exception {
+        createService();
+        mService.getBinderServiceInstance().suppressAmbientDisplay("test1", false);
+        mService.getBinderServiceInstance().suppressAmbientDisplay("test2", true);
+
+        assertThat(mService.getBinderServiceInstance().isAmbientDisplaySuppressed()).isTrue();
+    }
+
+    @Test
+    public void testIsAmbientDisplaySuppressed_multipleTokens_notSuppressed() throws Exception {
+        createService();
+        mService.getBinderServiceInstance().suppressAmbientDisplay("test1", false);
+        mService.getBinderServiceInstance().suppressAmbientDisplay("test2", false);
+
+        assertThat(mService.getBinderServiceInstance().isAmbientDisplaySuppressed()).isFalse();
+    }
+
+    @Test
+    public void testIsAmbientDisplaySuppressedForToken_default_notSuppressed() throws Exception {
+        createService();
+
+        assertThat(mService.getBinderServiceInstance().isAmbientDisplaySuppressedForToken("test"))
+            .isFalse();
+    }
+
+    @Test
+    public void testIsAmbientDisplaySuppressedForToken_suppressed() throws Exception {
+        createService();
+        mService.getBinderServiceInstance().suppressAmbientDisplay("test", true);
+
+        assertThat(mService.getBinderServiceInstance().isAmbientDisplaySuppressedForToken("test"))
+            .isTrue();
+    }
+
+    @Test
+    public void testIsAmbientDisplaySuppressedForToken_notSuppressed() throws Exception {
+        createService();
+        mService.getBinderServiceInstance().suppressAmbientDisplay("test", false);
+
+        assertThat(mService.getBinderServiceInstance().isAmbientDisplaySuppressedForToken("test"))
+            .isFalse();
+    }
+
+    @Test
+    public void testIsAmbientDisplaySuppressedForToken_multipleTokens_suppressed()
+            throws Exception {
+        createService();
+        mService.getBinderServiceInstance().suppressAmbientDisplay("test1", true);
+        mService.getBinderServiceInstance().suppressAmbientDisplay("test2", true);
+
+        assertThat(mService.getBinderServiceInstance().isAmbientDisplaySuppressedForToken("test1"))
+            .isTrue();
+        assertThat(mService.getBinderServiceInstance().isAmbientDisplaySuppressedForToken("test2"))
+            .isTrue();
+    }
+
+    @Test
+    public void testIsAmbientDisplaySuppressedForToken_multipleTokens_notSuppressed()
+            throws Exception {
+        createService();
+        mService.getBinderServiceInstance().suppressAmbientDisplay("test1", true);
+        mService.getBinderServiceInstance().suppressAmbientDisplay("test2", false);
+
+        assertThat(mService.getBinderServiceInstance().isAmbientDisplaySuppressedForToken("test1"))
+            .isTrue();
+        assertThat(mService.getBinderServiceInstance().isAmbientDisplaySuppressedForToken("test2"))
+            .isFalse();
+    }
 }
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index b1bd04e..0a03f14 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -66,6 +66,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.CompletableFuture;
 
 /**
@@ -345,7 +346,7 @@
 
     @Override
     public void setDevicePackage(UsbDevice device, String packageName, int userId) {
-        device = Preconditions.checkNotNull(device);
+        Objects.requireNonNull(device);
 
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
 
@@ -361,7 +362,7 @@
 
     @Override
     public void setAccessoryPackage(UsbAccessory accessory, String packageName, int userId) {
-        accessory = Preconditions.checkNotNull(accessory);
+        Objects.requireNonNull(accessory);
 
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
 
@@ -379,9 +380,9 @@
     @Override
     public void addDevicePackagesToPreferenceDenied(UsbDevice device, String[] packageNames,
             UserHandle user) {
-        device = Preconditions.checkNotNull(device);
+        Objects.requireNonNull(device);
         packageNames = Preconditions.checkArrayElementsNotNull(packageNames, "packageNames");
-        user = Preconditions.checkNotNull(user);
+        Objects.requireNonNull(user);
 
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
 
@@ -397,9 +398,9 @@
     @Override
     public void addAccessoryPackagesToPreferenceDenied(UsbAccessory accessory,
             String[] packageNames, UserHandle user) {
-        accessory = Preconditions.checkNotNull(accessory);
+        Objects.requireNonNull(accessory);
         packageNames = Preconditions.checkArrayElementsNotNull(packageNames, "packageNames");
-        user = Preconditions.checkNotNull(user);
+        Objects.requireNonNull(user);
 
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
 
@@ -415,9 +416,9 @@
     @Override
     public void removeDevicePackagesFromPreferenceDenied(UsbDevice device, String[] packageNames,
             UserHandle user) {
-        device = Preconditions.checkNotNull(device);
+        Objects.requireNonNull(device);
         packageNames = Preconditions.checkArrayElementsNotNull(packageNames, "packageNames");
-        user = Preconditions.checkNotNull(user);
+        Objects.requireNonNull(user);
 
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
 
@@ -433,9 +434,9 @@
     @Override
     public void removeAccessoryPackagesFromPreferenceDenied(UsbAccessory accessory,
             String[] packageNames, UserHandle user) {
-        accessory = Preconditions.checkNotNull(accessory);
+        Objects.requireNonNull(accessory);
         packageNames = Preconditions.checkArrayElementsNotNull(packageNames, "packageNames");
-        user = Preconditions.checkNotNull(user);
+        Objects.requireNonNull(user);
 
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
 
@@ -451,8 +452,8 @@
     @Override
     public void setDevicePersistentPermission(UsbDevice device, int uid, UserHandle user,
             boolean shouldBeGranted) {
-        device = Preconditions.checkNotNull(device);
-        user = Preconditions.checkNotNull(user);
+        Objects.requireNonNull(device);
+        Objects.requireNonNull(user);
 
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
 
@@ -468,8 +469,8 @@
     @Override
     public void setAccessoryPersistentPermission(UsbAccessory accessory, int uid,
             UserHandle user, boolean shouldBeGranted) {
-        accessory = Preconditions.checkNotNull(accessory);
-        user = Preconditions.checkNotNull(user);
+        Objects.requireNonNull(accessory);
+        Objects.requireNonNull(user);
 
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
 
@@ -663,7 +664,7 @@
 
     @Override
     public UsbPortStatus getPortStatus(String portId) {
-        Preconditions.checkNotNull(portId, "portId must not be null");
+        Objects.requireNonNull(portId, "portId must not be null");
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
 
         final long ident = Binder.clearCallingIdentity();
@@ -676,7 +677,7 @@
 
     @Override
     public void setPortRoles(String portId, int powerRole, int dataRole) {
-        Preconditions.checkNotNull(portId, "portId must not be null");
+        Objects.requireNonNull(portId, "portId must not be null");
         UsbPort.checkRoles(powerRole, dataRole);
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
 
@@ -692,7 +693,7 @@
 
     @Override
     public void enableContaminantDetection(String portId, boolean enable) {
-        Preconditions.checkNotNull(portId, "portId must not be null");
+        Objects.requireNonNull(portId, "portId must not be null");
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
 
         final long ident = Binder.clearCallingIdentity();
diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java
index 6d2ac9d..b1d647f 100644
--- a/telephony/java/android/telephony/AccessNetworkConstants.java
+++ b/telephony/java/android/telephony/AccessNetworkConstants.java
@@ -67,6 +67,22 @@
         }
     }
 
+    /**
+     * Access network type
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"RADIO_ACCESS_NETWORK_TYPE_"},
+            value = {
+                    AccessNetworkType.UNKNOWN,
+                    AccessNetworkType.GERAN,
+                    AccessNetworkType.UTRAN,
+                    AccessNetworkType.EUTRAN,
+                    AccessNetworkType.CDMA2000,
+                    AccessNetworkType.IWLAN,
+                    AccessNetworkType.NGRAN})
+    public @interface RadioAccessNetworkType {}
+
     public static final class AccessNetworkType {
         public static final int UNKNOWN = 0;
         public static final int GERAN = 1;
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index ff31d3e..7abad72 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -17,6 +17,7 @@
 package android.telephony;
 
 import android.Manifest;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -27,6 +28,7 @@
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
+import android.net.ipsec.ike.SaProposal;
 import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.service.carrier.CarrierService;
@@ -3417,6 +3419,369 @@
     public static final String KEY_PREVENT_CLIR_ACTIVATION_AND_DEACTIVATION_CODE_BOOL =
             "prevent_clir_activation_and_deactivation_code_bool";
 
+    /**
+     * Configs used for epdg tunnel bring up.
+     *
+     * @see <a href="https://tools.ietf.org/html/rfc7296">RFC 7296, Internet Key Exchange
+     *        Protocol Version 2 (IKEv2)</a>
+     */
+    public static final class Iwlan {
+        /** Prefix of all Epdg.KEY_* constants. */
+        public static final String KEY_PREFIX = "iwlan.";
+
+        /**
+         * Time in seconds after which the child security association session is terminated if
+         * rekey procedure is not successful. If not set or set to <= 0, the default value is
+         * 3600 seconds.
+         */
+        public static final String KEY_CHILD_SA_REKEY_HARD_TIMER_SEC_INT =
+                KEY_PREFIX + "child_sa_rekey_hard_timer_sec_int";
+
+        /**
+         * Time in seconds after which the child session rekey procedure is started. If not set or
+         * set to <= 0, default value is 3000 seconds.
+         */
+        public static final String KEY_CHILD_SA_REKEY_SOFT_TIMER_SEC_INT =
+                KEY_PREFIX + "child_sa_rekey_soft_timer_sec_int";
+
+        /** Supported DH groups for IKE negotiation.
+         * Possible values are {@link #DH_GROUP_NONE}, {@link #DH_GROUP_1024_BIT_MODP},
+         * {@link #DH_GROUP_2048_BIT_MODP}
+         */
+        public static final String KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY =
+                KEY_PREFIX + "diffie_hellman_groups_int_array";
+
+        /**
+         * Time in seconds after which a dead peer detection (DPD) request is sent.
+         * If not set or set to <= 0, default value is 120 seconds.
+         */
+        public static final String KEY_DPD_TIMER_SEC_INT = KEY_PREFIX + "dpd_timer_sec_int";
+
+        /**
+         * Method used to authenticate epdg server.
+         * Possible values are {@link #AUTHENTICATION_METHOD_EAP_ONLY},
+         * {@link #AUTHENTICATION_METHOD_CERT}
+         */
+        public static final String KEY_EPDG_AUTHENTICATION_METHOD_INT =
+                KEY_PREFIX + "epdg_authentication_method_int";
+
+        /**
+         * A priority list of ePDG addresses to be used.
+         * Possible values are {@link #EPDG_ADDRESS_STATIC}, {@link #EPDG_ADDRESS_PLMN},
+         * {@link #EPDG_ADDRESS_PCO}
+         */
+        public static final String KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY =
+                KEY_PREFIX + "epdg_address_priority_int_array";
+
+        /** Epdg static IP address or FQDN */
+        public static final String KEY_EPDG_STATIC_ADDRESS_STRING =
+                KEY_PREFIX + "epdg_static_address_string";
+
+        /** Epdg static IP address or FQDN for roaming */
+        public static final String KEY_EPDG_STATIC_ADDRESS_ROAMING_STRING =
+                KEY_PREFIX + "epdg_static_address_roaming_string";
+
+        /**
+         * List of supported key sizes for AES Cipher Block Chaining (CBC) encryption mode of child
+         * session.
+         * Possible values are {@link #KEY_LEN_UNUSED}, {@link #KEY_LEN_AES_128},
+         * {@link #KEY_LEN_AES_192}, {@link #KEY_LEN_AES_256}
+         */
+        public static final String KEY_CHILD_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY =
+                KEY_PREFIX + "child_session_aes_cbc_key_size_int_array";
+
+        /**
+         * List of supported key sizes for AES counter (CTR) encryption mode of child session.
+         * Possible values are {@link #KEY_LEN_UNUSED}, {@link #KEY_LEN_AES_128},
+         * {@link #KEY_LEN_AES_192}, {@link #KEY_LEN_AES_256}
+         */
+        public static final String KEY_CHILD_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY =
+                KEY_PREFIX + "child_encryption_aes_ctr_key_size_int_array";
+
+        /**
+         * List of supported encryption algorithms for child session.
+         * Possible values are {@link #ENCRYPTION_ALGORITHM_3DES},
+         * {@link #ENCRYPTION_ALGORITHM_AES_CBC}, {@link #ENCRYPTION_ALGORITHM_AES_GCM_8},
+         * {@link #ENCRYPTION_ALGORITHM_AES_GCM_12}, {@link #ENCRYPTION_ALGORITHM_AES_GCM_16}
+         */
+        public static final String KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY =
+                KEY_PREFIX + "supported_child_session_encryption_algorithms_int_array";
+
+        /** Controls if IKE message fragmentation is enabled. */
+        public static final String KEY_IKE_FRAGMENTATION_ENABLED_BOOL =
+                KEY_PREFIX + "ike_fragmentation_enabled_bool";
+
+        /**
+         * Time in seconds after which the IKE session is terminated if rekey procedure is not
+         * successful. If not set or set to <= 0, default value is 3600 seconds.
+         */
+        public static final String KEY_IKE_REKEY_HARD_TIMER_SEC_INT =
+                KEY_PREFIX + "ike_rekey_hard_timer_in_sec";
+
+        /**
+         * Time in seconds after which the IKE session rekey procedure is started. If not set or
+         * set to <= 0, default value is 3000 seconds.
+         */
+        public static final String KEY_IKE_REKEY_SOFT_TIMER_SEC_INT =
+                KEY_PREFIX + "ike_rekey_soft_timer_sec_int";
+
+        /**
+         * List of supported key sizes for AES Cipher Block Chaining (CBC) encryption mode of IKE
+         * session.
+         * Possible values - {@link #KEY_LEN_UNUSED}, {@link #KEY_LEN_AES_128},
+         *         {@link #KEY_LEN_AES_192}, {@link #KEY_LEN_AES_256}
+         */
+        public static final String KEY_IKE_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY =
+                KEY_PREFIX + "ike_session_encryption_aes_cbc_key_size_int_array";
+
+        /**
+         * List of supported key sizes for AES counter (CTR) encryption mode of IKE session.
+         * Possible values - {@link #KEY_LEN_UNUSED}, {@link #KEY_LEN_AES_128},
+         *         {@link #KEY_LEN_AES_192}, {@link #KEY_LEN_AES_256}
+         */
+        public static final String KEY_IKE_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY =
+                KEY_PREFIX + "ike_session_aes_ctr_key_size_int_array";
+
+        /**
+        * List of supported encryption algorithms for IKE session.
+        * Possible values are {@link #ENCRYPTION_ALGORITHM_3DES},
+         * {@link #ENCRYPTION_ALGORITHM_AES_CBC}, {@link #ENCRYPTION_ALGORITHM_AES_GCM_8},
+         * {@link #ENCRYPTION_ALGORITHM_AES_GCM_12}, {@link #ENCRYPTION_ALGORITHM_AES_GCM_16}
+        */
+        public static final String KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY =
+                KEY_PREFIX + "supported_ike_session_encryption_algorithms_int_array";
+
+        /**
+         * List of supported integrity algorithms for IKE session
+         * Possible values are {@link #INTEGRITY_ALGORITHM_NONE},
+         * {@link #INTEGRITY_ALGORITHM_HMAC_SHA1_96}, {@link #INTEGRITY_ALGORITHM_AES_XCBC_96},
+         * {@link #INTEGRITY_ALGORITHM_HMAC_SHA2_256_128},
+         * {@link #INTEGRITY_ALGORITHM_HMAC_SHA2_384_192},
+         * {@link #INTEGRITY_ALGORITHM_HMAC_SHA2_512_256}
+         */
+        public static final String KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY =
+                KEY_PREFIX + "supported_integrity_algorithms_int_array";
+
+        /** Maximum number of retries for tunnel establishment. */
+        public static final String KEY_MAX_RETRIES_INT = KEY_PREFIX + "max_retries_int";
+
+        /** Controls if nat traversal should be enabled. */
+        public static final String KEY_NATT_ENABLED_BOOL = KEY_PREFIX + "natt_enabled_bool";
+
+        /**
+         * Time in seconds after which a NATT keep alive message is sent. If not set or set to <= 0,
+         * default value is 20 seconds.
+         */
+        public static final String KEY_NATT_KEEP_ALIVE_TIMER_SEC_INT =
+                KEY_PREFIX + "natt_keep_alive_timer_sec_int";
+
+        /** List of comma separated MCC/MNCs used to create ePDG FQDN as per 3GPP TS 23.003 */
+        public static final String KEY_MCC_MNCS_STRING_ARRAY = KEY_PREFIX + "mcc_mncs_string_array";
+
+        /**
+         * List of supported pseudo random function algorithms for IKE session
+         * Possible values are {@link #PSEUDORANDOM_FUNCTION_HMAC_SHA1},
+         * {@link #PSEUDORANDOM_FUNCTION_AES128_XCBC}
+         */
+        public static final String KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY = KEY_PREFIX +
+                "supported_prf_algorithms_int_array";
+
+        /**
+         * Time in seconds after which IKE message is retransmitted. If not set or set to <= 0,
+         * default value is 2 seconds.
+         */
+        public static final String KEY_RETRANSMIT_TIMER_SEC_INT =
+                KEY_PREFIX + "retransmit_timer_sec_int";
+
+        /** @hide */
+        @IntDef({
+                AUTHENTICATION_METHOD_EAP_ONLY,
+                AUTHENTICATION_METHOD_CERT
+        })
+        public @interface AuthenticationMethodType {}
+
+        /**
+         * Certificate sent from the server is ignored. Only Extensible Authentication Protocol
+         * (EAP) is used to authenticate the server.
+         * EAP_ONLY_AUTH payload is added to IKE_AUTH request if supported.
+         * @see <a href="https://tools.ietf.org/html/rfc5998">RFC 5998</a>
+         */
+        public static final int AUTHENTICATION_METHOD_EAP_ONLY = 0;
+        /** Server is authenticated using its certificate. */
+        public static final int AUTHENTICATION_METHOD_CERT = 1;
+
+        /** @hide */
+        @IntDef({
+                EPDG_ADDRESS_STATIC,
+                EPDG_ADDRESS_PLMN,
+                EPDG_ADDRESS_PCO
+        })
+        public @interface EpdgAddressType {}
+
+        /** Use static epdg address. */
+        public static final int EPDG_ADDRESS_STATIC = 0;
+        /** Construct the epdg address using plmn. */
+        public static final int EPDG_ADDRESS_PLMN = 1;
+        /**
+         * Use the epdg address received in protocol configuration options (PCO) from the
+         * network.
+         */
+        public static final int EPDG_ADDRESS_PCO = 2;
+
+        /** @hide */
+        @IntDef({
+                KEY_LEN_UNUSED,
+                KEY_LEN_AES_128,
+                KEY_LEN_AES_192,
+                KEY_LEN_AES_256
+        })
+        public @interface EncrpytionKeyLengthType {}
+
+        public static final int KEY_LEN_UNUSED = SaProposal.KEY_LEN_UNUSED;
+        /** AES Encryption/Ciphering Algorithm key length 128 bits. */
+        public static final int KEY_LEN_AES_128 = SaProposal.KEY_LEN_AES_128;
+        /** AES Encryption/Ciphering Algorithm key length 192 bits. */
+        public static final int KEY_LEN_AES_192 = SaProposal.KEY_LEN_AES_192;
+        /** AES Encryption/Ciphering Algorithm key length 256 bits. */
+        public static final int KEY_LEN_AES_256 = SaProposal.KEY_LEN_AES_256;
+
+        /** @hide */
+        @IntDef({
+                DH_GROUP_NONE,
+                DH_GROUP_1024_BIT_MODP,
+                DH_GROUP_2048_BIT_MODP
+        })
+        public @interface DhGroup {}
+
+        /** None Diffie-Hellman Group. */
+        public static final int DH_GROUP_NONE = SaProposal.DH_GROUP_NONE;
+        /** 1024-bit MODP Diffie-Hellman Group. */
+        public static final int DH_GROUP_1024_BIT_MODP = SaProposal.DH_GROUP_1024_BIT_MODP;
+        /** 2048-bit MODP Diffie-Hellman Group. */
+        public static final int DH_GROUP_2048_BIT_MODP = SaProposal.DH_GROUP_2048_BIT_MODP;
+
+        /** @hide */
+        @IntDef({
+                ENCRYPTION_ALGORITHM_3DES,
+                ENCRYPTION_ALGORITHM_AES_CBC,
+                ENCRYPTION_ALGORITHM_AES_GCM_8,
+                ENCRYPTION_ALGORITHM_AES_GCM_12,
+                ENCRYPTION_ALGORITHM_AES_GCM_16
+        })
+        public @interface EncryptionAlgorithm {}
+
+        /** 3DES Encryption/Ciphering Algorithm. */
+        public static final int ENCRYPTION_ALGORITHM_3DES = SaProposal.ENCRYPTION_ALGORITHM_3DES;
+        /** AES-CBC Encryption/Ciphering Algorithm. */
+        public static final int ENCRYPTION_ALGORITHM_AES_CBC =
+                SaProposal.ENCRYPTION_ALGORITHM_AES_CBC;
+
+        /**
+         * AES-GCM Authentication/Integrity + Encryption/Ciphering Algorithm with 8-octet ICV
+         * (truncation).
+         */
+        public static final int ENCRYPTION_ALGORITHM_AES_GCM_8 =
+                SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8;
+        /**
+         * AES-GCM Authentication/Integrity + Encryption/Ciphering Algorithm with 12-octet ICV
+         * (truncation).
+         */
+        public static final int ENCRYPTION_ALGORITHM_AES_GCM_12 =
+                SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12;
+        /**
+         * AES-GCM Authentication/Integrity + Encryption/Ciphering Algorithm with 16-octet ICV
+         * (truncation).
+         */
+        public static final int ENCRYPTION_ALGORITHM_AES_GCM_16 =
+                SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16;
+
+        /** @hide */
+        @IntDef({
+                INTEGRITY_ALGORITHM_NONE,
+                INTEGRITY_ALGORITHM_HMAC_SHA1_96,
+                INTEGRITY_ALGORITHM_AES_XCBC_96,
+                INTEGRITY_ALGORITHM_HMAC_SHA2_256_128,
+                INTEGRITY_ALGORITHM_HMAC_SHA2_384_192,
+                INTEGRITY_ALGORITHM_HMAC_SHA2_512_256
+        })
+        public @interface IntegrityAlgorithm {}
+
+        /** None Authentication/Integrity Algorithm. */
+        public static final int INTEGRITY_ALGORITHM_NONE = SaProposal.INTEGRITY_ALGORITHM_NONE;
+        /** HMAC-SHA1 Authentication/Integrity Algorithm. */
+        public static final int INTEGRITY_ALGORITHM_HMAC_SHA1_96 =
+                SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96;
+        /** AES-XCBC-96 Authentication/Integrity Algorithm. */
+        public static final int INTEGRITY_ALGORITHM_AES_XCBC_96 =
+                SaProposal.INTEGRITY_ALGORITHM_AES_XCBC_96;
+        /** HMAC-SHA256 Authentication/Integrity Algorithm with 128-bit truncation. */
+        public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_256_128 =
+                SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128;
+        /** HMAC-SHA384 Authentication/Integrity Algorithm with 192-bit truncation. */
+        public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_384_192 =
+                SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_384_192;
+        /** HMAC-SHA512 Authentication/Integrity Algorithm with 256-bit truncation. */
+        public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_512_256 =
+                SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_512_256;
+
+        /** @hide */
+        @IntDef({
+                PSEUDORANDOM_FUNCTION_HMAC_SHA1,
+                PSEUDORANDOM_FUNCTION_AES128_XCBC
+        })
+        public @interface PseudorandomFunction {}
+
+        /** HMAC-SHA1 Pseudorandom Function. */
+        public static final int PSEUDORANDOM_FUNCTION_HMAC_SHA1 =
+                SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1;
+        /** AES128-XCBC Pseudorandom Function. */
+        public static final int PSEUDORANDOM_FUNCTION_AES128_XCBC =
+                SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC;
+
+        private Iwlan() {}
+
+        private static PersistableBundle getDefaults() {
+            PersistableBundle defaults = new PersistableBundle();
+            defaults.putInt(KEY_IKE_REKEY_SOFT_TIMER_SEC_INT, 3000);
+            defaults.putInt(KEY_IKE_REKEY_HARD_TIMER_SEC_INT, 3600);
+            defaults.putInt(KEY_CHILD_SA_REKEY_SOFT_TIMER_SEC_INT, 3000);
+            defaults.putInt(KEY_CHILD_SA_REKEY_HARD_TIMER_SEC_INT, 3600);
+            defaults.putInt(KEY_RETRANSMIT_TIMER_SEC_INT, 2);
+            defaults.putInt(KEY_DPD_TIMER_SEC_INT, 120);
+            defaults.putInt(KEY_MAX_RETRIES_INT, 3);
+            defaults.putIntArray(KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY,
+                    new int[]{DH_GROUP_1024_BIT_MODP, DH_GROUP_2048_BIT_MODP});
+            defaults.putIntArray(KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY,
+                    new int[]{ENCRYPTION_ALGORITHM_3DES, ENCRYPTION_ALGORITHM_AES_CBC});
+            defaults.putIntArray(KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY,
+                    new int[]{ENCRYPTION_ALGORITHM_3DES, ENCRYPTION_ALGORITHM_AES_CBC});
+            defaults.putIntArray(KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY,
+                    new int[]{INTEGRITY_ALGORITHM_AES_XCBC_96, INTEGRITY_ALGORITHM_HMAC_SHA1_96,
+                            INTEGRITY_ALGORITHM_HMAC_SHA2_256_128});
+            defaults.putIntArray(KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY,
+                    new int[]{PSEUDORANDOM_FUNCTION_HMAC_SHA1, PSEUDORANDOM_FUNCTION_AES128_XCBC});
+            defaults.putBoolean(KEY_NATT_ENABLED_BOOL, true);
+            defaults.putInt(KEY_EPDG_AUTHENTICATION_METHOD_INT, AUTHENTICATION_METHOD_CERT);
+            defaults.putString(KEY_EPDG_STATIC_ADDRESS_STRING, "");
+            defaults.putString(KEY_EPDG_STATIC_ADDRESS_ROAMING_STRING, "");
+            defaults.putInt(KEY_NATT_KEEP_ALIVE_TIMER_SEC_INT, 20);
+            defaults.putIntArray(KEY_IKE_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY,
+                    new int[]{KEY_LEN_AES_128, KEY_LEN_AES_256});
+            defaults.putIntArray(KEY_IKE_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY,
+                    new int[]{KEY_LEN_AES_128});
+            defaults.putIntArray(KEY_CHILD_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY,
+                    new int[]{KEY_LEN_AES_128, KEY_LEN_AES_256});
+            defaults.putIntArray(KEY_CHILD_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY,
+                    new int[]{KEY_LEN_AES_128});
+            defaults.putBoolean(KEY_IKE_FRAGMENTATION_ENABLED_BOOL, false);
+            defaults.putIntArray(KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY, new int[]{EPDG_ADDRESS_PLMN,
+                    EPDG_ADDRESS_STATIC});
+            defaults.putStringArray(KEY_MCC_MNCS_STRING_ARRAY, new String[]{});
+
+            return defaults;
+        }
+    }
+
     /** The default value for every variable. */
     private final static PersistableBundle sDefaults;
 
@@ -3908,6 +4273,7 @@
         // Default wifi configurations.
         sDefaults.putAll(Wifi.getDefaults());
         sDefaults.putBoolean(ENABLE_EAP_METHOD_PREFIX_BOOL, false);
+        sDefaults.putAll(Iwlan.getDefaults());
     }
 
     /**
diff --git a/telephony/java/android/telephony/CdmaEriInformation.java b/telephony/java/android/telephony/CdmaEriInformation.java
new file mode 100644
index 0000000..1cd9d30
--- /dev/null
+++ b/telephony/java/android/telephony/CdmaEriInformation.java
@@ -0,0 +1,170 @@
+/**
+ * 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 android.telephony;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * CDMA ERI (Enhanced Roaming Indicator) information.
+ *
+ * This contains the following ERI information
+ *
+ * 1. ERI (Enhanced Roaming Indicator) icon index. The number is assigned by
+ *    3GPP2 C.R1001-H v1.0 Table 8.1-1. Additionally carriers define their own
+ *    ERI icon index.
+ * 2. CDMA ERI icon mode. This represents how the icon should be displayed.
+ *    Its one of the following CDMA ERI icon mode
+ *    {@link android.telephony.CdmaEriInformation#ERI_ICON_MODE_NORMAL}
+ *    {@link android.telephony.CdmaEriInformation#ERI_ICON_MODE_FLASH}
+ *
+ * @hide
+ */
+@SystemApi
+public final class CdmaEriInformation implements Parcelable {
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"ERI_"}, value = {
+                ERI_ON,
+                ERI_OFF,
+                ERI_FLASH
+            })
+    public @interface EriIconIndex {}
+
+    /**
+     * ERI (Enhanced Roaming Indicator) is ON i.e value 0 defined by
+     * 3GPP2 C.R1001-H v1.0 Table 8.1-1.
+     */
+    public static final int ERI_ON = 0;
+
+    /**
+     * ERI (Enhanced Roaming Indicator) is OFF i.e value 1 defined by
+     * 3GPP2 C.R1001-H v1.0 Table 8.1-1.
+     */
+    public static final int ERI_OFF = 1;
+
+    /**
+     * ERI (Enhanced Roaming Indicator) is FLASH i.e value 2 defined by
+     * 3GPP2 C.R1001-H v1.0 Table 8.1-1.
+     */
+    public static final int ERI_FLASH = 2;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"ERI_ICON_MODE_"}, value = {
+                ERI_ICON_MODE_NORMAL,
+                ERI_ICON_MODE_FLASH
+            })
+    public @interface EriIconMode {}
+
+    /**
+     * ERI (Enhanced Roaming Indicator) icon mode is normal. This constant represents that
+     * the ERI icon should be displayed normally.
+     *
+     * Note: ERI is defined 3GPP2 C.R1001-H Table 8.1-1
+     */
+    public static final int ERI_ICON_MODE_NORMAL = 0;
+
+    /**
+     * ERI (Enhanced Roaming Indicator) icon mode flash. This constant represents that
+     * the ERI icon should be flashing.
+     *
+     * Note: ERI is defined 3GPP2 C.R1001-H Table 8.1-1
+     */
+    public static final int ERI_ICON_MODE_FLASH = 1;
+
+    private @EriIconIndex int mIconIndex;
+    private @EriIconMode int mIconMode;
+
+    /**
+     * Creates CdmaEriInformation from iconIndex and iconMode
+     *
+     * @hide
+     */
+    public CdmaEriInformation(@EriIconIndex int iconIndex, @EriIconMode int iconMode) {
+        mIconIndex = iconIndex;
+        mIconMode = iconMode;
+    }
+
+    /** Gets the ERI icon index */
+    public @EriIconIndex int getEriIconIndex() {
+        return mIconIndex;
+    }
+
+    /**
+     * Sets the ERI icon index
+     *
+     * @hide
+     */
+    public void setEriIconIndex(@EriIconIndex int iconIndex) {
+        mIconIndex = iconIndex;
+    }
+
+    /** Gets the ERI icon mode */
+    public @EriIconMode int getEriIconMode() {
+        return mIconMode;
+    }
+
+    /**
+     * Sets the ERI icon mode
+     *
+     * @hide
+     */
+    public void setEriIconMode(@EriIconMode int iconMode) {
+        mIconMode = iconMode;
+    }
+    /** Implement the Parcelable interface */
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(mIconIndex);
+        dest.writeInt(mIconMode);
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Construct a CdmaEriInformation object from the given parcel
+     */
+    private CdmaEriInformation(Parcel in) {
+        mIconIndex = in.readInt();
+        mIconMode = in.readInt();
+    }
+
+    /** Implement the Parcelable interface */
+    public static final @android.annotation.NonNull Parcelable.Creator<CdmaEriInformation> CREATOR =
+            new Parcelable.Creator<CdmaEriInformation>() {
+        @Override
+        public CdmaEriInformation createFromParcel(Parcel in) {
+            return new CdmaEriInformation(in);
+        }
+
+        @Override
+        public CdmaEriInformation[] newArray(int size) {
+            return new CdmaEriInformation[size];
+        }
+    };
+}
diff --git a/telephony/java/android/telephony/PhoneCapability.java b/telephony/java/android/telephony/PhoneCapability.java
index 8a75831..90244b3 100644
--- a/telephony/java/android/telephony/PhoneCapability.java
+++ b/telephony/java/android/telephony/PhoneCapability.java
@@ -16,13 +16,20 @@
 
 package android.telephony;
 
+import android.annotation.LongDef;
 import android.annotation.NonNull;
-import android.annotation.SystemApi;
+import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.telephony.AccessNetworkConstants.AccessNetworkType;
+import android.telephony.AccessNetworkConstants.RadioAccessNetworkType;
+import android.telephony.TelephonyManager.NetworkTypeBitMask;
 
+import com.android.internal.util.CollectionUtils;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
 
@@ -31,68 +38,365 @@
  * are shared between those modems defined by list of modem IDs.
  */
 public final class PhoneCapability implements Parcelable {
-    // Hardcoded default DSDS capability.
+    /** Modem feature indicating 3GPP2 capability. */
+    public static final long MODEM_FEATURE_3GPP2_REG = 1 << 0;
+    /** Modem feature indicating 3GPP capability. */
+    public static final long MODEM_FEATURE_3GPP_REG = 1 << 1;
+    /** Modem feature indicating CDMA 2000 with EHRPD capability. */
+    public static final long MODEM_FEATURE_CDMA2000_EHRPD_REG = 1 << 2;
+    /** Modem feature indicating GSM capability. */
+    public static final long MODEM_FEATURE_GERAN_REG = 1 << 3;
+    /** Modem feature indicating UMTS capability. */
+    public static final long MODEM_FEATURE_UTRAN_REG = 1 << 4;
+    /** Modem feature indicating LTE capability. */
+    public static final long MODEM_FEATURE_EUTRAN_REG = 1 << 5;
+    /** Modem feature indicating 5G capability.*/
+    public static final long MODEM_FEATURE_NGRAN_REG = 1 << 6;
+    /** Modem feature indicating EN-DC capability. */
+    public static final long MODEM_FEATURE_EUTRA_NR_DUAL_CONNECTIVITY_REG = 1 << 7;
+    /** Modem feature indicating VoLTE capability (IMS registered). */
+    public static final long MODEM_FEATURE_PS_VOICE_REG = 1 << 8;
+    /** Modem feature indicating CS voice call capability. */
+    public static final long MODEM_FEATURE_CS_VOICE_SESSION = 1 << 9;
+    /** Modem feature indicating Internet connection capability. */
+    public static final long MODEM_FEATURE_INTERACTIVE_DATA_SESSION = 1 << 10;
+    /**
+     * Modem feature indicating dedicated bearer capability.
+     * For services that require a high level QoS (eg. VoLTE), the network can create
+     * a dedicated bearer with the required QoS on top of an established default bearer.
+     * This will provide a dedicated tunnel for one or more specific traffic types.
+     */
+    public static final long MODEM_FEATURE_DEDICATED_BEARER = 1 << 11;
+    /** Modem feature indicating network scan capability. */
+    public static final long MODEM_FEATURE_NETWORK_SCAN = 1 << 12;
+    /** Modem feature indicating corresponding SIM has CDMA capability. */
+    public static final long MODEM_FEATURE_CSIM = 1 << 13;
+
     /** @hide */
+    @LongDef(flag = true, prefix = {"MODEM_FEATURE_" }, value = {
+            MODEM_FEATURE_3GPP2_REG,
+            MODEM_FEATURE_3GPP_REG,
+            MODEM_FEATURE_CDMA2000_EHRPD_REG,
+            MODEM_FEATURE_GERAN_REG,
+            MODEM_FEATURE_UTRAN_REG,
+            MODEM_FEATURE_EUTRAN_REG,
+            MODEM_FEATURE_NGRAN_REG,
+            MODEM_FEATURE_EUTRA_NR_DUAL_CONNECTIVITY_REG,
+            MODEM_FEATURE_PS_VOICE_REG,
+            MODEM_FEATURE_CS_VOICE_SESSION,
+            MODEM_FEATURE_INTERACTIVE_DATA_SESSION,
+            MODEM_FEATURE_DEDICATED_BEARER,
+            MODEM_FEATURE_NETWORK_SCAN,
+            MODEM_FEATURE_CSIM,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ModemFeature {
+    }
+
+    /**
+     * Hardcoded default DSDS capability.
+     * @hide
+     */
     public static final PhoneCapability DEFAULT_DSDS_CAPABILITY;
-    // Hardcoded default Single SIM single standby capability.
-    /** @hide */
+    /**
+     * Hardcoded default Single SIM single standby capability.
+     * @hide
+     */
     public static final PhoneCapability DEFAULT_SSSS_CAPABILITY;
 
     static {
-        ModemInfo modemInfo1 = new ModemInfo(0, 0, true, true);
-        ModemInfo modemInfo2 = new ModemInfo(1, 0, true, true);
+        List<List<Long>> capabilities = new ArrayList<>();
+        List<Long> modem1 = new ArrayList<>();
+        List<Long> modem2 = new ArrayList<>();
+        modem1.add(MODEM_FEATURE_GERAN_REG | MODEM_FEATURE_UTRAN_REG | MODEM_FEATURE_EUTRAN_REG
+                | MODEM_FEATURE_PS_VOICE_REG | MODEM_FEATURE_CS_VOICE_SESSION
+                | MODEM_FEATURE_INTERACTIVE_DATA_SESSION | MODEM_FEATURE_DEDICATED_BEARER);
+        modem2.add(MODEM_FEATURE_GERAN_REG | MODEM_FEATURE_UTRAN_REG | MODEM_FEATURE_EUTRAN_REG
+                | MODEM_FEATURE_PS_VOICE_REG | MODEM_FEATURE_INTERACTIVE_DATA_SESSION
+                | MODEM_FEATURE_DEDICATED_BEARER);
+        capabilities.add(modem1);
+        capabilities.add(modem2);
+        List<String> uuids = new ArrayList<>();
+        uuids.add("com.xxxx.lm0");
+        uuids.add("com.xxxx.lm1");
+        long rats = TelephonyManager.NETWORK_TYPE_BITMASK_GSM
+                | TelephonyManager.NETWORK_TYPE_BITMASK_GPRS
+                | TelephonyManager.NETWORK_TYPE_BITMASK_EDGE
+                | TelephonyManager.NETWORK_TYPE_BITMASK_UMTS
+                | TelephonyManager.NETWORK_TYPE_BITMASK_LTE;
+        DEFAULT_DSDS_CAPABILITY = new PhoneCapability(0, 0, 0, 0, 0, rats, null, null, null, null,
+                uuids, null, capabilities);
 
-        List<ModemInfo> logicalModemList = new ArrayList<>();
-        logicalModemList.add(modemInfo1);
-        logicalModemList.add(modemInfo2);
-        DEFAULT_DSDS_CAPABILITY = new PhoneCapability(1, 1, 0, logicalModemList, false);
-
-        logicalModemList = new ArrayList<>();
-        logicalModemList.add(modemInfo1);
-        DEFAULT_SSSS_CAPABILITY = new PhoneCapability(1, 1, 0, logicalModemList, false);
+        capabilities = new ArrayList<>();
+        capabilities.add(modem1);
+        uuids = new ArrayList<>();
+        uuids.add("com.xxxx.lm0");
+        DEFAULT_SSSS_CAPABILITY = new PhoneCapability(0, 0, 0, 0, 0, rats, null, null, null, null,
+                uuids, null, capabilities);
     }
-    /** @hide */
-    public final int maxActiveVoiceCalls;
-    /** @hide */
-    public final int maxActiveData;
-    /** @hide */
-    public final int max5G;
-    /** @hide */
-    public final boolean validationBeforeSwitchSupported;
-    /** @hide */
-    public final List<ModemInfo> logicalModemList;
 
-    /** @hide */
-    public PhoneCapability(int maxActiveVoiceCalls, int maxActiveData, int max5G,
-            List<ModemInfo> logicalModemList, boolean validationBeforeSwitchSupported) {
-        this.maxActiveVoiceCalls = maxActiveVoiceCalls;
-        this.maxActiveData = maxActiveData;
-        this.max5G = max5G;
-        // Make sure it's not null.
-        this.logicalModemList = logicalModemList == null ? new ArrayList<>() : logicalModemList;
-        this.validationBeforeSwitchSupported = validationBeforeSwitchSupported;
+    private final int mUtranUeCategoryDl;
+    private final int mUtranUeCategoryUl;
+    private final int mEutranUeCategoryDl;
+    private final int mEutranUeCategoryUl;
+    private final long mPsDataConnectionLingerTimeMillis;
+    private final @NetworkTypeBitMask long mSupportedRats;
+    private final List<Integer> mGeranBands;
+    private final List<Integer> mUtranBands;
+    private final List<Integer> mEutranBands;
+    private final List<Integer> mNgranBands;
+    private final List<String> mLogicalModemUuids;
+    private final List<SimSlotCapability> mSimSlotCapabilities;
+    private final @ModemFeature List<List<Long>> mConcurrentFeaturesSupport;
+
+    /**
+     * Default constructor to create a PhoneCapability object.
+     * @param utranUeCategoryDl 3GPP UE category for UTRAN downlink.
+     * @param utranUeCategoryUl 3GPP UE category for UTRAN uplink.
+     * @param eutranUeCategoryDl 3GPP UE category for EUTRAN downlink.
+     * @param eutranUeCategoryUl 3GPP UE category for EUTRAN uplink.
+     * @param psDataConnectionLingerTimeMillis length of the grace period to allow a smooth
+     *                                         "handover" between data connections.
+     * @param supportedRats all radio access technologies this phone is capable of supporting.
+     * @param geranBands list of supported {@link AccessNetworkConstants.GeranBand}.
+     * @param utranBands list of supported {@link AccessNetworkConstants.UtranBand}.
+     * @param eutranBands list of supported {@link AccessNetworkConstants.EutranBand}.
+     * @param ngranBands list of supported {@link AccessNetworkConstants.NgranBands}.
+     * @param logicalModemUuids list of logical modem UUIDs, typically of the form
+     *                          "com.xxxx.lmX", where X is the logical modem ID.
+     * @param simSlotCapabilities list of {@link SimSlotCapability} for the device
+     * @param concurrentFeaturesSupport list of list of concurrently supportable modem feature sets.
+     * @hide
+     */
+    public PhoneCapability(int utranUeCategoryDl, int utranUeCategoryUl, int eutranUeCategoryDl,
+            int eutranUeCategoryUl, long psDataConnectionLingerTimeMillis,
+            @NetworkTypeBitMask long supportedRats, @Nullable List<Integer> geranBands,
+            @Nullable List<Integer> utranBands, @Nullable List<Integer> eutranBands,
+            @Nullable List<Integer> ngranBands, @Nullable List<String> logicalModemUuids,
+            @Nullable List<SimSlotCapability> simSlotCapabilities,
+            @Nullable @ModemFeature List<List<Long>> concurrentFeaturesSupport) {
+        this.mUtranUeCategoryDl = utranUeCategoryDl;
+        this.mUtranUeCategoryUl = utranUeCategoryUl;
+        this.mEutranUeCategoryDl = eutranUeCategoryDl;
+        this.mEutranUeCategoryUl = eutranUeCategoryUl;
+        this.mPsDataConnectionLingerTimeMillis = psDataConnectionLingerTimeMillis;
+        this.mSupportedRats = supportedRats;
+        this.mGeranBands = CollectionUtils.emptyIfNull(geranBands);
+        this.mUtranBands = CollectionUtils.emptyIfNull(utranBands);
+        this.mEutranBands = CollectionUtils.emptyIfNull(eutranBands);
+        this.mNgranBands = CollectionUtils.emptyIfNull(ngranBands);
+        this.mLogicalModemUuids = CollectionUtils.emptyIfNull(logicalModemUuids);
+        this.mSimSlotCapabilities = CollectionUtils.emptyIfNull(simSlotCapabilities);
+        this.mConcurrentFeaturesSupport = CollectionUtils.emptyIfNull(concurrentFeaturesSupport);
+    }
+
+    private PhoneCapability(Parcel in) {
+        mUtranUeCategoryDl = in.readInt();
+        mUtranUeCategoryUl = in.readInt();
+        mEutranUeCategoryDl = in.readInt();
+        mEutranUeCategoryUl = in.readInt();
+        mPsDataConnectionLingerTimeMillis = in.readLong();
+        mSupportedRats = in.readLong();
+        mGeranBands = new ArrayList<>();
+        in.readList(mGeranBands, Integer.class.getClassLoader());
+        mUtranBands = new ArrayList<>();
+        in.readList(mUtranBands, Integer.class.getClassLoader());
+        mEutranBands = new ArrayList<>();
+        in.readList(mEutranBands, Integer.class.getClassLoader());
+        mNgranBands = new ArrayList<>();
+        in.readList(mNgranBands, Integer.class.getClassLoader());
+        mLogicalModemUuids = in.createStringArrayList();
+        mSimSlotCapabilities = in.createTypedArrayList(SimSlotCapability.CREATOR);
+        int length = in.readInt();
+        mConcurrentFeaturesSupport = new ArrayList<>();
+        for (int i = 0; i < length; i++) {
+            ArrayList<Long> feature = new ArrayList<>();
+            in.readList(feature, Long.class.getClassLoader());
+            mConcurrentFeaturesSupport.add(feature);
+        }
+    }
+
+    /**
+     * 3GPP UE category for a given Radio Access Network and direction.
+     *
+     * References are:
+     * TS 25.306 Table 4.1a     EUTRAN downlink
+     * TS 25.306 Table 5.1a-2   EUTRAN uplink
+     * TS 25.306 Table 5.1a     UTRAN downlink
+     * TS 25.306 Table 5.1g     UTRAN uplink
+     *
+     * @param uplink true for uplink direction and false for downlink direction.
+     * @param accessNetworkType accessNetworkType, defined in {@link AccessNetworkType}.
+     * @return the UE category, or -1 if it is not supported.
+     */
+    public int getUeCategory(boolean uplink, @RadioAccessNetworkType int accessNetworkType) {
+        if (uplink) {
+            switch (accessNetworkType) {
+                case AccessNetworkType.UTRAN: return mUtranUeCategoryUl;
+                case AccessNetworkType.EUTRAN: return mEutranUeCategoryUl;
+                default: return -1;
+            }
+        } else {
+            switch (accessNetworkType) {
+                case AccessNetworkType.UTRAN: return mUtranUeCategoryDl;
+                case AccessNetworkType.EUTRAN: return mEutranUeCategoryDl;
+                default: return -1;
+            }
+        }
+    }
+
+    /**
+     * In cellular devices that support a greater number of logical modems than
+     * Internet connections, some devices support a grace period to allow a smooth "handover"
+     * between those connections. If that feature is supported, then this API will provide
+     * the length of that grace period in milliseconds. If it is not supported, the default value
+     * for the grace period is 0.
+     * @return handover linger time in milliseconds, or 0 if it is not supported.
+     */
+    public long getPsDataConnectionLingerTimeMillis() {
+        return mPsDataConnectionLingerTimeMillis;
+    }
+
+    /**
+     * The radio access technologies this device is capable of supporting.
+     * @return a bitfield of all supported network types, defined in {@link TelephonyManager}
+     */
+    public @NetworkTypeBitMask long getSupportedRats() {
+        return mSupportedRats;
+    }
+
+    /**
+     * List of supported cellular bands for the given accessNetworkType.
+     * @param accessNetworkType accessNetworkType, defined in {@link AccessNetworkType}.
+     * @return a list of bands, or an empty list if the access network type is unsupported.
+     */
+    public @NonNull List<Integer> getBands(@RadioAccessNetworkType int accessNetworkType) {
+        switch (accessNetworkType) {
+            case AccessNetworkType.GERAN: return mGeranBands;
+            case AccessNetworkType.UTRAN: return mUtranBands;
+            case AccessNetworkType.EUTRAN: return mEutranBands;
+            case AccessNetworkType.NGRAN: return mNgranBands;
+            default: return new ArrayList<>();
+        }
+    }
+
+    /**
+     * List of logical modem UUIDs, each typically "com.xxxx.lmX", where X is the logical modem ID.
+     * @return a list of modem UUIDs, one for every logical modem the device has.
+     */
+    public @NonNull List<String> getLogicalModemUuids() {
+        return mLogicalModemUuids;
+    }
+
+    /**
+     * List of {@link SimSlotCapability} for the device. The order of SIMs corresponds to the
+     * order of modems in {@link #getLogicalModemUuids}.
+     * @return a list of SIM slot capabilities, one for every SIM slot the device has.
+     */
+    public @NonNull List<SimSlotCapability> getSimSlotCapabilities() {
+        return mSimSlotCapabilities;
+    }
+
+    /**
+     * A List of Lists of concurrently supportable modem feature sets.
+     *
+     * Each entry in the top-level list is an independent configuration across all modems
+     * that describes the capabilities of the device as a whole.
+     *
+     * Each entry in the second-level list is a bitfield of ModemFeatures that describes
+     * the capabilities for a single modem. In the second-level list, the order of the modems
+     * corresponds to order of the UUIDs in {@link #getLogicalModemUuids}.
+     *
+     * For symmetric capabilities that can only be active on one modem at a time, there will be
+     * multiple configurations (equal to the number of modems) that shows it active on each modem.
+     * For asymmetric capabilities that are only available on one of the modems, all configurations
+     * will have that capability on just that one modem.
+     *
+     * The example below shows the concurrentFeaturesSupport for a 3-modem device with
+     * theoretical capabilities SYMMETRIC (available on all modems, but only one at a time) and
+     * ASYMMETRIC (only available on the first modem):
+     * {
+     *      Configuration 1: ASYMMETRIC and SYMMETRIC on modem 1, modem 2 empty, modem 3 empty
+     *      {(ASYMMETRIC | SYMMETRIC), (), ()},
+     *
+     *      Configuration 2: ASYMMETRIC on modem 1, SYMMETRIC on modem 2, modem 3 empty
+     *      {(ASYMMETRIC), (SYMMETRIC), ()},
+     *
+     *      Configuration 3: ASYMMETRIC on modem 1, modem 2 empty, SYMMETRIC on modem 3
+     *      {(ASYMMETRIC), (), (SYMMETRIC)}
+     * }
+     *
+     * @return List of all concurrently supportable modem features.
+     */
+    public @NonNull @ModemFeature List<List<Long>> getConcurrentFeaturesSupport() {
+        return mConcurrentFeaturesSupport;
+    }
+
+    /**
+     * How many modems can simultaneously have PS attached.
+     * @return maximum number of active PS voice connections.
+     */
+    public int getMaxActivePsVoice() {
+        return countFeature(MODEM_FEATURE_PS_VOICE_REG);
+    }
+
+    /**
+     * How many modems can simultaneously support active data connections.
+     * For DSDS, this will be 1, and for DSDA this will be 2.
+     * @return maximum number of active Internet data sessions.
+     */
+    public int getMaxActiveInternetData() {
+        return countFeature(MODEM_FEATURE_INTERACTIVE_DATA_SESSION);
+    }
+
+    /**
+     * How many modems can simultaneously have dedicated bearer capability.
+     * @return maximum number of active dedicated bearers.
+     */
+    public int getMaxActiveDedicatedBearers() {
+        return countFeature(MODEM_FEATURE_DEDICATED_BEARER);
+    }
+
+    /**
+     * Whether the CBRS band 48 is supported or not.
+     * @return true if any RadioAccessNetwork supports CBRS and false if none do.
+     * @hide
+     */
+    public boolean isCbrsSupported() {
+        return mEutranBands.contains(AccessNetworkConstants.EutranBand.BAND_48)
+                || mNgranBands.contains(AccessNetworkConstants.NgranBands.BAND_48);
+    }
+
+    private int countFeature(@ModemFeature long feature) {
+        int count = 0;
+        for (long featureSet : mConcurrentFeaturesSupport.get(0)) {
+            if ((featureSet & feature) != 0) {
+                count++;
+            }
+        }
+        return count;
     }
 
     @Override
     public String toString() {
-        return "maxActiveVoiceCalls=" + maxActiveVoiceCalls + " maxActiveData=" + maxActiveData
-                + " max5G=" + max5G + "logicalModemList:"
-                + Arrays.toString(logicalModemList.toArray());
-    }
-
-    private PhoneCapability(Parcel in) {
-        maxActiveVoiceCalls = in.readInt();
-        maxActiveData = in.readInt();
-        max5G = in.readInt();
-        validationBeforeSwitchSupported = in.readBoolean();
-        logicalModemList = new ArrayList<>();
-        in.readList(logicalModemList, ModemInfo.class.getClassLoader());
+        return "utranUeCategoryDl=" + mUtranUeCategoryDl
+                + " utranUeCategoryUl=" + mUtranUeCategoryUl
+                + " eutranUeCategoryDl=" + mEutranUeCategoryDl
+                + " eutranUeCategoryUl=" + mEutranUeCategoryUl
+                + " psDataConnectionLingerTimeMillis=" + mPsDataConnectionLingerTimeMillis
+                + " supportedRats=" + mSupportedRats + " geranBands=" + mGeranBands
+                + " utranBands=" + mUtranBands + " eutranBands=" + mEutranBands
+                + " ngranBands=" + mNgranBands + " logicalModemUuids=" + mLogicalModemUuids
+                + " simSlotCapabilities=" + mSimSlotCapabilities
+                + " concurrentFeaturesSupport=" + mConcurrentFeaturesSupport;
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(maxActiveVoiceCalls, maxActiveData, max5G, logicalModemList,
-                validationBeforeSwitchSupported);
+        return Objects.hash(mUtranUeCategoryDl, mUtranUeCategoryUl, mEutranUeCategoryDl,
+                mEutranUeCategoryUl, mPsDataConnectionLingerTimeMillis, mSupportedRats, mGeranBands,
+                mUtranBands, mEutranBands, mNgranBands, mLogicalModemUuids, mSimSlotCapabilities,
+                mConcurrentFeaturesSupport);
     }
 
     @Override
@@ -107,11 +411,19 @@
 
         PhoneCapability s = (PhoneCapability) o;
 
-        return (maxActiveVoiceCalls == s.maxActiveVoiceCalls
-                && maxActiveData == s.maxActiveData
-                && max5G == s.max5G
-                && validationBeforeSwitchSupported == s.validationBeforeSwitchSupported
-                && logicalModemList.equals(s.logicalModemList));
+        return (mUtranUeCategoryDl == s.mUtranUeCategoryDl
+                && mUtranUeCategoryUl == s.mUtranUeCategoryUl
+                && mEutranUeCategoryDl == s.mEutranUeCategoryDl
+                && mEutranUeCategoryUl == s.mEutranUeCategoryUl
+                && mPsDataConnectionLingerTimeMillis == s.mPsDataConnectionLingerTimeMillis
+                && mSupportedRats == s.mSupportedRats
+                && mGeranBands.equals(s.mGeranBands)
+                && mUtranBands.equals(s.mUtranBands)
+                && mEutranBands.equals(s.mEutranBands)
+                && mNgranBands.equals(s.mNgranBands)
+                && mLogicalModemUuids.equals(s.mLogicalModemUuids)
+                && mSimSlotCapabilities.equals(s.mSimSlotCapabilities)
+                && mConcurrentFeaturesSupport.equals(s.mConcurrentFeaturesSupport));
     }
 
     /**
@@ -125,20 +437,32 @@
      * {@link Parcelable#writeToParcel}
      */
     public void writeToParcel(@NonNull Parcel dest, @Parcelable.WriteFlags int flags) {
-        dest.writeInt(maxActiveVoiceCalls);
-        dest.writeInt(maxActiveData);
-        dest.writeInt(max5G);
-        dest.writeBoolean(validationBeforeSwitchSupported);
-        dest.writeList(logicalModemList);
+        dest.writeInt(mUtranUeCategoryDl);
+        dest.writeInt(mUtranUeCategoryUl);
+        dest.writeInt(mEutranUeCategoryDl);
+        dest.writeInt(mEutranUeCategoryUl);
+        dest.writeLong(mPsDataConnectionLingerTimeMillis);
+        dest.writeLong(mSupportedRats);
+        dest.writeList(mGeranBands);
+        dest.writeList(mUtranBands);
+        dest.writeList(mEutranBands);
+        dest.writeList(mNgranBands);
+        dest.writeStringList(mLogicalModemUuids);
+        dest.writeTypedList(mSimSlotCapabilities);
+        dest.writeInt(mConcurrentFeaturesSupport.size());
+        for (List<Long> feature : mConcurrentFeaturesSupport) {
+            dest.writeList(feature);
+        }
     }
 
-    public static final @android.annotation.NonNull Parcelable.Creator<PhoneCapability> CREATOR = new Parcelable.Creator() {
-        public PhoneCapability createFromParcel(Parcel in) {
-            return new PhoneCapability(in);
-        }
+    public static final @NonNull Parcelable.Creator<PhoneCapability> CREATOR =
+            new Parcelable.Creator() {
+                public PhoneCapability createFromParcel(Parcel in) {
+                    return new PhoneCapability(in);
+                }
 
-        public PhoneCapability[] newArray(int size) {
-            return new PhoneCapability[size];
-        }
-    };
+                public PhoneCapability[] newArray(int size) {
+                    return new PhoneCapability[size];
+                }
+            };
 }
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 2f9e6ac..0074772 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -28,7 +28,6 @@
 import android.content.Intent;
 import android.content.res.Resources;
 import android.database.Cursor;
-import android.location.CountryDetector;
 import android.net.Uri;
 import android.os.PersistableBundle;
 import android.provider.Contacts;
@@ -2032,6 +2031,7 @@
     private static boolean isEmergencyNumberInternal(int subId, String number,
                                                      String defaultCountryIso,
                                                      boolean useExactMatch) {
+        // TODO: clean up all the callers that pass in a defaultCountryIso, since it's ignored now.
         try {
             if (useExactMatch) {
                 return TelephonyManager.getDefault().isEmergencyNumber(number);
@@ -2193,18 +2193,7 @@
     private static boolean isLocalEmergencyNumberInternal(int subId, String number,
                                                           Context context,
                                                           boolean useExactMatch) {
-        String countryIso;
-        CountryDetector detector = (CountryDetector) context.getSystemService(
-                Context.COUNTRY_DETECTOR);
-        if (detector != null && detector.detectCountry() != null) {
-            countryIso = detector.detectCountry().getCountryIso();
-        } else {
-            Locale locale = context.getResources().getConfiguration().locale;
-            countryIso = locale.getCountry();
-            Rlog.w(LOG_TAG, "No CountryDetector; falling back to countryIso based on locale: "
-                    + countryIso);
-        }
-        return isEmergencyNumberInternal(subId, number, countryIso, useExactMatch);
+        return isEmergencyNumberInternal(subId, number, null /* unused */, useExactMatch);
     }
 
     /**
diff --git a/telephony/java/android/telephony/PreciseDataConnectionState.java b/telephony/java/android/telephony/PreciseDataConnectionState.java
index 0cfb8c5..094b8b0 100644
--- a/telephony/java/android/telephony/PreciseDataConnectionState.java
+++ b/telephony/java/android/telephony/PreciseDataConnectionState.java
@@ -135,7 +135,7 @@
     }
 
     /**
-     * To check the SDK version for {@link PreciseDataConnectionState#getDataConnectionState}.
+     * To check the SDK version for {@code PreciseDataConnectionState#getDataConnectionState}.
      */
     @ChangeId
     @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
diff --git a/telephony/java/android/telephony/SimSlotCapability.java b/telephony/java/android/telephony/SimSlotCapability.java
new file mode 100644
index 0000000..3d38d04
--- /dev/null
+++ b/telephony/java/android/telephony/SimSlotCapability.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2019 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 android.telephony;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * Capabilities for a SIM Slot.
+ */
+public final class SimSlotCapability implements Parcelable {
+    /** Slot type for UICC (removable SIM). */
+    public static final int SLOT_TYPE_UICC = 1;
+    /** Slot type for iUICC/iSIM (integrated SIM). */
+    public static final int SLOT_TYPE_IUICC = 2;
+    /** Slot type for eUICC/eSIM (embedded SIM). */
+    public static final int SLOT_TYPE_EUICC = 3;
+    /** Slot type for soft SIM (no physical SIM). */
+    public static final int SLOT_TYPE_SOFT_SIM = 4;
+
+    /** @hide */
+    @IntDef(prefix = {"SLOT_TYPE_" }, value = {
+            SLOT_TYPE_UICC,
+            SLOT_TYPE_IUICC,
+            SLOT_TYPE_EUICC,
+            SLOT_TYPE_SOFT_SIM,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SlotType {
+    }
+
+    private final int mPhysicalSlotIndex;
+    private final int mSlotType;
+
+    /** @hide */
+    public SimSlotCapability(int physicalSlotId, int slotType) {
+        this.mPhysicalSlotIndex = physicalSlotId;
+        this.mSlotType = slotType;
+    }
+
+    private SimSlotCapability(Parcel in) {
+        mPhysicalSlotIndex = in.readInt();
+        mSlotType = in.readInt();
+    }
+
+    /**
+     * @return physical SIM slot index
+     */
+    public int getPhysicalSlotIndex() {
+        return mPhysicalSlotIndex;
+    }
+
+    /**
+     * @return type of SIM {@link SlotType}
+     */
+    public @SlotType int getSlotType() {
+        return mSlotType;
+    }
+
+    @Override
+    public String toString() {
+        return "mPhysicalSlotIndex=" + mPhysicalSlotIndex + " slotType=" + mSlotType;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mPhysicalSlotIndex, mSlotType);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == null || !(o instanceof SimSlotCapability) || hashCode() != o.hashCode()) {
+            return false;
+        }
+
+        if (this == o) {
+            return true;
+        }
+
+        SimSlotCapability s = (SimSlotCapability) o;
+
+        return (mPhysicalSlotIndex == s.mPhysicalSlotIndex && mSlotType == s.mSlotType);
+    }
+
+    /**
+     * {@link Parcelable#describeContents}
+     */
+    public @ContentsFlags int describeContents() {
+        return 0;
+    }
+
+    /**
+     * {@link Parcelable#writeToParcel}
+     */
+    public void writeToParcel(@NonNull Parcel dest, @WriteFlags int flags) {
+        dest.writeInt(mPhysicalSlotIndex);
+        dest.writeInt(mSlotType);
+    }
+
+    public static final @NonNull Parcelable.Creator<SimSlotCapability> CREATOR =
+            new Parcelable.Creator() {
+                public SimSlotCapability createFromParcel(Parcel in) {
+                    return new SimSlotCapability(in);
+                }
+
+                public SimSlotCapability[] newArray(int size) {
+                    return new SimSlotCapability[size];
+                }
+            };
+}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 92fafdc..075b56b 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -94,6 +94,7 @@
 import com.android.ims.internal.IImsServiceFeatureCallback;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.CellNetworkScanResult;
+import com.android.internal.telephony.IBooleanConsumer;
 import com.android.internal.telephony.INumberVerificationCallback;
 import com.android.internal.telephony.IOns;
 import com.android.internal.telephony.IPhoneSubInfo;
@@ -193,11 +194,8 @@
                     NETWORK_SELECTION_MODE_MANUAL})
     public @interface NetworkSelectionMode {}
 
-    /** @hide */
     public static final int NETWORK_SELECTION_MODE_UNKNOWN = 0;
-    /** @hide */
     public static final int NETWORK_SELECTION_MODE_AUTO = 1;
-    /** @hide */
     public static final int NETWORK_SELECTION_MODE_MANUAL = 2;
 
     /** The otaspMode passed to PhoneStateListener#onOtaspChanged */
@@ -1364,6 +1362,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final String EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE =
             "android.telephony.extra.DEFAULT_SUBSCRIPTION_SELECT_TYPE";
 
@@ -1383,6 +1382,7 @@
      * to indicate there's no need to re-select any default subscription.
      * @hide
      */
+    @SystemApi
     public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE = 0;
 
     /**
@@ -1390,6 +1390,7 @@
      * to indicate there's a need to select default data subscription.
      * @hide
      */
+    @SystemApi
     public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA = 1;
 
     /**
@@ -1397,6 +1398,7 @@
      * to indicate there's a need to select default voice call subscription.
      * @hide
      */
+    @SystemApi
     public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_VOICE = 2;
 
     /**
@@ -1404,6 +1406,7 @@
      * to indicate there's a need to select default sms subscription.
      * @hide
      */
+    @SystemApi
     public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_SMS = 3;
 
     /**
@@ -1413,6 +1416,7 @@
      * which subscription should be the default subscription.
      * @hide
      */
+    @SystemApi
     public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL = 4;
 
     /**
@@ -1422,6 +1426,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final String EXTRA_SIM_COMBINATION_WARNING_TYPE =
             "android.telephony.extra.SIM_COMBINATION_WARNING_TYPE";
 
@@ -1438,6 +1443,7 @@
      * to indicate there's no SIM combination warning.
      * @hide
      */
+    @SystemApi
     public static final int EXTRA_SIM_COMBINATION_WARNING_TYPE_NONE = 0;
 
     /**
@@ -1445,6 +1451,7 @@
      * to indicate two active SIMs are both CDMA hence there might be functional limitation.
      * @hide
      */
+    @SystemApi
     public static final int EXTRA_SIM_COMBINATION_WARNING_TYPE_DUAL_CDMA = 1;
 
     /**
@@ -1455,6 +1462,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final String EXTRA_SIM_COMBINATION_NAMES =
             "android.telephony.extra.SIM_COMBINATION_NAMES";
 
@@ -1776,6 +1784,24 @@
     //
 
     /**
+     * Returns the {@link PhoneCapability} for the device or null if it is not available.
+     * <p>
+     * Requires Permission: READ_PHONE_STATE or that the calling app has
+     * carrier privileges (see {@link #hasCarrierPrivileges}).
+     */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @Nullable
+    public PhoneCapability getPhoneCapability() {
+        try {
+            ITelephony telephony = getITelephony();
+            return telephony == null ? null :
+                    telephony.getPhoneCapability(getSubId(), getOpPackageName(), getFeatureId());
+        } catch (RemoteException ex) {
+            return null;
+        }
+    }
+
+    /**
      * Returns the software version number for the device, for example,
      * the IMEI/SV for GSM phones. Return null if the software version is
      * not available.
@@ -5613,19 +5639,25 @@
     }
 
     /**
-     * Returns the CDMA ERI icon index to display
+     * Get the CDMA ERI (Enhanced Roaming Indicator) information
+     *
+     * Returns {@link android.telephony#CdmaEriInformation}
+     *
      * @hide
      */
-    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
-    public int getCdmaEriIconIndex() {
-        return getCdmaEriIconIndex(getSubId());
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    @SystemApi
+    @NonNull
+    public CdmaEriInformation getCdmaEriInformation() {
+        return new CdmaEriInformation(
+               getCdmaEriIconMode(getSubId()), getCdmaEriIconIndex(getSubId()));
     }
 
     /**
      * Returns the CDMA ERI icon index to display for a subscription
      * @hide
      */
-    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     @UnsupportedAppUsage
     public int getCdmaEriIconIndex(int subId) {
         try {
@@ -5643,25 +5675,13 @@
     }
 
     /**
-     * Returns the CDMA ERI icon mode,
-     * 0 - ON
-     * 1 - FLASHING
-     *
-     * @hide
-     */
-    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
-    public int getCdmaEriIconMode() {
-        return getCdmaEriIconMode(getSubId());
-    }
-
-    /**
      * Returns the CDMA ERI icon mode for a subscription.
      * 0 - ON
      * 1 - FLASHING
      *
      * @hide
      */
-    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     @UnsupportedAppUsage
     public int getCdmaEriIconMode(int subId) {
         try {
@@ -7947,14 +7967,18 @@
      *
      * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
      * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
-
-     * @return the network selection mode.
+     *  <p>Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE
+     * READ_PRECISE_PHONE_STATE}
+     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
-     * @hide
+     * @return the network selection mode.
      */
-    @NetworkSelectionMode
-    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
-    public int getNetworkSelectionMode() {
+    @SuppressAutoDoc // No support for carrier privileges (b/72967236).
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+            android.Manifest.permission.READ_PRECISE_PHONE_STATE
+    })
+    public @NetworkSelectionMode int getNetworkSelectionMode() {
         int mode = NETWORK_SELECTION_MODE_UNKNOWN;
         try {
             ITelephony telephony = getITelephony();
@@ -12521,6 +12545,51 @@
     }
 
     /**
+     * Specify which bands modem's background scan must act on.
+     * If {@code specifiers} is non-empty, the scan will be restricted to the bands specified.
+     * Otherwise, it scans all bands.
+     *
+     * For example, CBRS is only on LTE band 48. By specifying this band,
+     * modem saves more power.
+     *
+     * @param specifiers which bands to scan.
+     * @param executor The executor to execute the callback on
+     * @param callback The callback that gets invoked when the radio responds to the request. Called
+     *                 with {@code true} if the request succeeded, {@code false} otherwise.
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public void setSystemSelectionChannels(@NonNull List<RadioAccessSpecifier> specifiers,
+            @Nullable @CallbackExecutor Executor executor,
+            @Nullable Consumer<Boolean> callback) {
+        Objects.requireNonNull(specifiers, "Specifiers must not be null.");
+        if (callback != null) {
+            Objects.requireNonNull(executor, "Executor must not be null when"
+                    + " the callback is nonnull");
+        }
+
+        IBooleanConsumer aidlConsumer = callback == null ? null : new IBooleanConsumer.Stub() {
+            @Override
+            public void accept(boolean result) {
+                executor.execute(() -> callback.accept(result));
+            }
+        };
+
+        try {
+            ITelephony service = getITelephony();
+            if (service != null) {
+                service.setSystemSelectionChannels(specifiers, getSubId(), aidlConsumer);
+            }
+        } catch (RemoteException ex) {
+            if (!isSystemProcess()) {
+                ex.rethrowAsRuntimeException();
+            }
+        }
+    }
+
+    /**
      * Verifies whether the input MCC/MNC and MVNO correspond to the current carrier.
      *
      * @param mccmnc the carrier's mccmnc that you want to match
diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java
index 49625bb..a116c07 100644
--- a/telephony/java/android/telephony/data/DataCallResponse.java
+++ b/telephony/java/android/telephony/data/DataCallResponse.java
@@ -78,6 +78,9 @@
     private final List<InetAddress> mGatewayAddresses;
     private final List<InetAddress> mPcscfAddresses;
     private final int mMtu;
+    private final int mMtuV4;
+    private final int mMtuV6;
+    private final int mVersion;
 
     /**
      * @param cause Data call fail cause. {@link DataFailCause#NONE} indicates no error.
@@ -97,9 +100,8 @@
      * "192.0.1.11 2001:db8::1". When null, the addresses represent point to point connections.
      * @param pcscfAddresses A list of Proxy Call State Control Function address via PCO (Protocol
      * Configuration Option) for IMS client.
-     * @param mtu MTU (maximum transmission unit) in bytes received from network. Zero or negative
-     * values means network has either not sent a value or sent an invalid value.
-     * either not sent a value or sent an invalid value.
+     * @param mtu MTU (maximum transmission unit) in bytes received from network.
+     * Zero or negative values means network has either not sent a value or sent an invalid value.
      *
      * @removed Use the {@link Builder()} instead.
      */
@@ -125,6 +127,34 @@
         mPcscfAddresses = (pcscfAddresses == null)
                 ? new ArrayList<>() : new ArrayList<>(pcscfAddresses);
         mMtu = mtu;
+        mMtuV4 = mMtuV6 = 0;
+        mVersion = 0;
+    }
+
+    /** @hide */
+    private DataCallResponse(@DataFailureCause int cause, int suggestedRetryTime, int id,
+            @LinkStatus int linkStatus, @ProtocolType int protocolType,
+            @Nullable String interfaceName, @Nullable List<LinkAddress> addresses,
+            @Nullable List<InetAddress> dnsAddresses, @Nullable List<InetAddress> gatewayAddresses,
+            @Nullable List<InetAddress> pcscfAddresses, int mtuV4, int mtuV6, int version) {
+        mCause = cause;
+        mSuggestedRetryTime = suggestedRetryTime;
+        mId = id;
+        mLinkStatus = linkStatus;
+        mProtocolType = protocolType;
+        mInterfaceName = (interfaceName == null) ? "" : interfaceName;
+        mAddresses = (addresses == null)
+                ? new ArrayList<>() : new ArrayList<>(addresses);
+        mDnsAddresses = (dnsAddresses == null)
+                ? new ArrayList<>() : new ArrayList<>(dnsAddresses);
+        mGatewayAddresses = (gatewayAddresses == null)
+                ? new ArrayList<>() : new ArrayList<>(gatewayAddresses);
+        mPcscfAddresses = (pcscfAddresses == null)
+                ? new ArrayList<>() : new ArrayList<>(pcscfAddresses);
+        mMtu = 0;
+        mMtuV4 = mtuV4;
+        mMtuV6 = mtuV6;
+        mVersion = version;
     }
 
     /** @hide */
@@ -145,6 +175,9 @@
         mPcscfAddresses = new ArrayList<>();
         source.readList(mPcscfAddresses, InetAddress.class.getClassLoader());
         mMtu = source.readInt();
+        mMtuV4 = source.readInt();
+        mMtuV6 = source.readInt();
+        mVersion = source.readInt();
     }
 
     /**
@@ -210,8 +243,29 @@
     /**
      * @return MTU (maximum transmission unit) in bytes received from network. Zero or negative
      * values means network has either not sent a value or sent an invalid value.
+     * @deprecated For IRadio 1.5 and up, use {@link #getMtuV4} or {@link #getMtuV6} instead.
      */
-    public int getMtu() { return mMtu; }
+    @Deprecated
+    public int getMtu() {
+        return mVersion < 5 ? mMtu : 0;
+    }
+
+    /**
+     * This replaces the deprecated method getMtu.
+     * @return MTU (maximum transmission unit) in bytes received from network, for IPv4.
+     * Zero or negative values means network has either not sent a value or sent an invalid value.
+     */
+    public int getMtuV4() {
+        return mVersion < 5 ? 0 : mMtuV4;
+    }
+
+    /**
+     * @return MTU (maximum transmission unit) in bytes received from network, for IPv6.
+     * Zero or negative values means network has either not sent a value or sent an invalid value.
+     */
+    public int getMtuV6() {
+        return mVersion < 5 ? 0 : mMtuV6;
+    }
 
     @NonNull
     @Override
@@ -229,6 +283,9 @@
            .append(" gateways=").append(mGatewayAddresses)
            .append(" pcscf=").append(mPcscfAddresses)
            .append(" mtu=").append(mMtu)
+           .append(" mtuV4=").append(mMtuV4)
+           .append(" mtuV6=").append(mMtuV6)
+           .append(" version=").append(mVersion)
            .append("}");
         return sb.toString();
     }
@@ -256,14 +313,17 @@
                 && mGatewayAddresses.containsAll(other.mGatewayAddresses)
                 && mPcscfAddresses.size() == other.mPcscfAddresses.size()
                 && mPcscfAddresses.containsAll(other.mPcscfAddresses)
-                && mMtu == other.mMtu;
+                && mMtu == other.mMtu
+                && mMtuV4 == other.mMtuV4
+                && mMtuV6 == other.mMtuV6
+                && mVersion == other.mVersion;
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(mCause, mSuggestedRetryTime, mId, mLinkStatus, mProtocolType,
                 mInterfaceName, mAddresses, mDnsAddresses, mGatewayAddresses, mPcscfAddresses,
-                mMtu);
+                mMtu, mMtuV4, mMtuV6, mVersion);
     }
 
     @Override
@@ -284,6 +344,9 @@
         dest.writeList(mGatewayAddresses);
         dest.writeList(mPcscfAddresses);
         dest.writeInt(mMtu);
+        dest.writeInt(mMtuV4);
+        dest.writeInt(mMtuV6);
+        dest.writeInt(mVersion);
     }
 
     public static final @android.annotation.NonNull Parcelable.Creator<DataCallResponse> CREATOR =
@@ -336,6 +399,12 @@
 
         private int mMtu;
 
+        private int mMtuV4;
+
+        private int mMtuV6;
+
+        private int mVersion;
+
         /**
          * Default constructor for Builder.
          */
@@ -460,6 +529,7 @@
          * negative values means network has either not sent a value or sent an invalid value.
          *
          * @return The same instance of the builder.
+         * @deprecated For IRadio 1.5 and up, use {@link #setMtuV4} or {@link #setMtuV6} instead.
          */
         public @NonNull Builder setMtu(int mtu) {
             mMtu = mtu;
@@ -467,14 +537,55 @@
         }
 
         /**
+         * Set maximum transmission unit of the data connection, for IPv4.
+         *
+         * @param mtu MTU (maximum transmission unit) in bytes received from network. Zero or
+         * negative values means network has either not sent a value or sent an invalid value.
+         *
+         * @return The same instance of the builder.
+         */
+        public @NonNull Builder setMtuV4(int mtu) {
+            mMtuV4 = mtu;
+            return this;
+        }
+
+        /**
+         * Set maximum transmission unit of the data connection, for IPv6.
+         *
+         * @param mtu MTU (maximum transmission unit) in bytes received from network. Zero or
+         * negative values means network has either not sent a value or sent an invalid value.
+         *
+         * @return The same instance of the builder.
+         */
+        public @NonNull Builder setMtuV6(int mtu) {
+            mMtuV6 = mtu;
+            return this;
+        }
+
+        /**
+         * Set the IRadio version for this DataCallResponse
+         * @hide
+         */
+        public @NonNull Builder setVersion(int version) {
+            mVersion = version;
+            return this;
+        }
+
+        /**
          * Build the DataCallResponse.
          *
          * @return the DataCallResponse object.
          */
         public @NonNull DataCallResponse build() {
-            return new DataCallResponse(mCause, mSuggestedRetryTime, mId, mLinkStatus,
-                    mProtocolType, mInterfaceName, mAddresses, mDnsAddresses, mGatewayAddresses,
-                    mPcscfAddresses, mMtu);
+            if (mVersion >= 5) {
+                return new DataCallResponse(mCause, mSuggestedRetryTime, mId, mLinkStatus,
+                        mProtocolType, mInterfaceName, mAddresses, mDnsAddresses, mGatewayAddresses,
+                        mPcscfAddresses, mMtuV4, mMtuV6, mVersion);
+            } else {
+                return new DataCallResponse(mCause, mSuggestedRetryTime, mId, mLinkStatus,
+                        mProtocolType, mInterfaceName, mAddresses, mDnsAddresses, mGatewayAddresses,
+                        mPcscfAddresses, mMtu);
+            }
         }
     }
 }
diff --git a/telephony/java/android/telephony/data/DataProfile.java b/telephony/java/android/telephony/data/DataProfile.java
index 96a5a81..f2a1249 100644
--- a/telephony/java/android/telephony/data/DataProfile.java
+++ b/telephony/java/android/telephony/data/DataProfile.java
@@ -96,7 +96,9 @@
     @NetworkTypeBitMask
     private final int mBearerBitmask;
 
-    private final int mMtu;
+    private final int mMtuV4;
+
+    private final int mMtuV6;
 
     private final boolean mPersistent;
 
@@ -104,12 +106,11 @@
 
     /** @hide */
     private DataProfile(int profileId, String apn, @ProtocolType int protocolType, int authType,
-                        String userName, String password, int type, int maxConnectionsTime,
-                        int maxConnections, int waitTime, boolean enabled,
-                        @ApnType int supportedApnTypesBitmask,
-                        @ProtocolType int roamingProtocolType,
-                        @NetworkTypeBitMask int bearerBitmask, int mtu, boolean persistent,
-                        boolean preferred) {
+            String userName, String password, int type, int maxConnectionsTime,
+            int maxConnections, int waitTime, boolean enabled,
+            @ApnType int supportedApnTypesBitmask, @ProtocolType int roamingProtocolType,
+            @NetworkTypeBitMask int bearerBitmask, int mtuV4, int mtuV6, boolean persistent,
+            boolean preferred) {
         this.mProfileId = profileId;
         this.mApn = apn;
         this.mProtocolType = protocolType;
@@ -128,7 +129,8 @@
         this.mSupportedApnTypesBitmask = supportedApnTypesBitmask;
         this.mRoamingProtocolType = roamingProtocolType;
         this.mBearerBitmask = bearerBitmask;
-        this.mMtu = mtu;
+        this.mMtuV4 = mtuV4;
+        this.mMtuV6 = mtuV6;
         this.mPersistent = persistent;
         this.mPreferred = preferred;
     }
@@ -148,7 +150,8 @@
         mSupportedApnTypesBitmask = source.readInt();
         mRoamingProtocolType = source.readInt();
         mBearerBitmask = source.readInt();
-        mMtu = source.readInt();
+        mMtuV4 = source.readInt();
+        mMtuV6 = source.readInt();
         mPersistent = source.readBoolean();
         mPreferred = source.readBoolean();
     }
@@ -237,8 +240,21 @@
 
     /**
      * @return The maximum transmission unit (MTU) size in bytes.
+     * @deprecated use {@link #getMtuV4} or {@link #getMtuV6} instead.
      */
-    public int getMtu() { return mMtu; }
+    @Deprecated
+    public int getMtu() { return mMtuV4; }
+
+    /**
+     * This replaces the deprecated method getMtu.
+     * @return The maximum transmission unit (MTU) size in bytes, for IPv4.
+     */
+    public int getMtuV4() { return mMtuV4; }
+
+    /**
+     * @return The maximum transmission unit (MTU) size in bytes, for IPv6.
+     */
+    public int getMtuV6() { return mMtuV6; }
 
     /**
      * @return {@code true} if modem must persist this data profile.
@@ -265,8 +281,8 @@
                          (mApn + "/" + mUserName + "/" + mPassword)) + "/" + mType + "/"
                 + mMaxConnectionsTime + "/" + mMaxConnections + "/"
                 + mWaitTime + "/" + mEnabled + "/" + mSupportedApnTypesBitmask + "/"
-                + mRoamingProtocolType + "/" + mBearerBitmask + "/" + mMtu + "/" + mPersistent + "/"
-                + mPreferred;
+                + mRoamingProtocolType + "/" + mBearerBitmask + "/" + mMtuV4 + "/" + mMtuV6 + "/"
+                + mPersistent + "/" + mPreferred;
     }
 
     @Override
@@ -285,7 +301,8 @@
         dest.writeInt(mSupportedApnTypesBitmask);
         dest.writeInt(mRoamingProtocolType);
         dest.writeInt(mBearerBitmask);
-        dest.writeInt(mMtu);
+        dest.writeInt(mMtuV4);
+        dest.writeInt(mMtuV6);
         dest.writeBoolean(mPersistent);
         dest.writeBoolean(mPreferred);
     }
@@ -319,7 +336,8 @@
                 && mSupportedApnTypesBitmask == that.mSupportedApnTypesBitmask
                 && mRoamingProtocolType == that.mRoamingProtocolType
                 && mBearerBitmask == that.mBearerBitmask
-                && mMtu == that.mMtu
+                && mMtuV4 == that.mMtuV4
+                && mMtuV6 == that.mMtuV6
                 && mPersistent == that.mPersistent
                 && mPreferred == that.mPreferred
                 && Objects.equals(mApn, that.mApn)
@@ -331,8 +349,8 @@
     public int hashCode() {
         return Objects.hash(mProfileId, mApn, mProtocolType, mAuthType, mUserName, mPassword, mType,
                 mMaxConnectionsTime, mMaxConnections, mWaitTime, mEnabled,
-                mSupportedApnTypesBitmask, mRoamingProtocolType, mBearerBitmask, mMtu, mPersistent,
-                mPreferred);
+                mSupportedApnTypesBitmask, mRoamingProtocolType, mBearerBitmask, mMtuV4, mMtuV6,
+                mPersistent, mPreferred);
     }
 
     /**
@@ -384,7 +402,9 @@
         @NetworkTypeBitMask
         private int mBearerBitmask;
 
-        private int mMtu;
+        private int mMtuV4;
+
+        private int mMtuV6;
 
         private boolean mPersistent;
 
@@ -567,9 +587,33 @@
          *
          * @param mtu The maximum transmission unit (MTU) size in bytes.
          * @return The same instance of the builder.
+         * @deprecated use {@link #setMtuV4} or {@link #setMtuV6} instead.
          */
         public @NonNull Builder setMtu(int mtu) {
-            mMtu = mtu;
+            mMtuV4 = mMtuV6 = mtu;
+            return this;
+        }
+
+        /**
+         * Set the maximum transmission unit (MTU) size in bytes, for IPv4.
+         * This replaces the deprecated method setMtu.
+         *
+         * @param mtu The maximum transmission unit (MTU) size in bytes.
+         * @return The same instance of the builder.
+         */
+        public @NonNull Builder setMtuV4(int mtu) {
+            mMtuV4 = mtu;
+            return this;
+        }
+
+        /**
+         * Set the maximum transmission unit (MTU) size in bytes, for IPv6.
+         *
+         * @param mtu The maximum transmission unit (MTU) size in bytes.
+         * @return The same instance of the builder.
+         */
+        public @NonNull Builder setMtuV6(int mtu) {
+            mMtuV6 = mtu;
             return this;
         }
 
@@ -606,7 +650,7 @@
         public @NonNull DataProfile build() {
             return new DataProfile(mProfileId, mApn, mProtocolType, mAuthType, mUserName, mPassword,
                     mType, mMaxConnectionsTime, mMaxConnections, mWaitTime, mEnabled,
-                    mSupportedApnTypesBitmask, mRoamingProtocolType, mBearerBitmask, mMtu,
+                    mSupportedApnTypesBitmask, mRoamingProtocolType, mBearerBitmask, mMtuV4, mMtuV6,
                     mPersistent, mPreferred);
         }
     }
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index 8c11df4..0370846 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -101,6 +101,101 @@
 
     // Inheriting values from ImsConfig for backwards compatibility.
     /**
+     * AMR CODEC Mode Value set, 0-7 in comma separated sequence.
+     * <p>
+     * This corresponds to the {@code mode-set} parameter for the AMR codec.
+     * See 3GPP TS 26.101 Table 1A for more information.
+     * <p>
+     * <UL>
+     *     <LI>0 - AMR 4.75 kbit/s</LI>
+     *     <LI>1 - AMR 5.15 kbit/s</LI>
+     *     <LI>2 - AMR 5.90 kbit/s</LI>
+     *     <LI>3 - AMR 6.70 kbit/s (PDC-EFR)</LI>
+     *     <LI>4 - AMR 7.40 kbit/s (TDMA-EFR)</LI>
+     *     <LI>5 - AMR 7.95 kbit/s</LI>
+     *     <LI>6 - AMR 10.2 kbit/s</LI>
+     *     <LI>7 - AMR 12.2 kbit/s (GSM-EFR)</LI>
+     * </UL>
+     * <p>
+     * Value is in String format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_AMR_CODEC_MODE_SET_VALUES = 0;
+
+    /**
+     * Wide Band AMR CODEC Mode Value set,0-7 in comma separated sequence.
+     * <p>
+     * This corresponds to the {@code mode-set} parameter for the AMR wideband codec.
+     * See 3GPP TS 26.101 Table 1A for more information.
+     * <p>
+     * <UL>
+     *     <LI>0 - AMR 4.75 kbit/s</LI>
+     *     <LI>1 - AMR 5.15 kbit/s</LI>
+     *     <LI>2 - AMR 5.90 kbit/s</LI>
+     *     <LI>3 - AMR 6.70 kbit/s (PDC-EFR)</LI>
+     *     <LI>4 - AMR 7.40 kbit/s (TDMA-EFR)</LI>
+     *     <LI>5 - AMR 7.95 kbit/s</LI>
+     *     <LI>6 - AMR 10.2 kbit/s</LI>
+     *     <LI>7 - AMR 12.2 kbit/s (GSM-EFR)</LI>
+     * </UL>
+     * <p>
+     * Value is in String format.
+     * @see #setProvisioningStringValue(int, String)
+     * @see #getProvisioningStringValue(int)
+     */
+    public static final int KEY_AMR_WB_CODEC_MODE_SET_VALUES = 1;
+
+    /**
+     * SIP Session Timer value (seconds).
+     * <p>
+     * See RFC4028 for more information.
+     * <p>
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_SIP_SESSION_TIMER_SEC = 2;
+
+    /**
+     * Minimum SIP Session Expiration Timer in (seconds).
+     * <p>
+     * See RFC4028 for more information.
+     * <p>
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_MINIMUM_SIP_SESSION_EXPIRATION_TIMER_SEC = 3;
+
+    /**
+     * SIP_INVITE cancellation time out value (in milliseconds). Integer format.
+     * <p>
+     * See RFC4028 for more information.
+     * <p>
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_SIP_INVITE_CANCELLATION_TIMER_MS = 4;
+
+    /**
+     * Delay time when an iRAT transitions from eHRPD/HRPD/1xRTT to LTE.
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_TRANSITION_TO_LTE_DELAY_MS = 5;
+
+    /**
+     * Silent redial status of Enabled (True), or Disabled (False).
+     * Value is in boolean format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_ENABLE_SILENT_REDIAL = 6;
+
+    /**
      * An integer key representing the SIP T1 timer value in milliseconds for the associated
      * subscription.
      * <p>
@@ -116,6 +211,28 @@
     public static final int KEY_T1_TIMER_VALUE_MS = 7;
 
     /**
+     * SIP T2 timer value in milliseconds.  See RFC 3261 for information.
+     * <p>
+     * The T2 timer is the maximum retransmit interval for non-INVITE requests and INVITE responses.
+     * <p>
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_T2_TIMER_VALUE_MS = 8;
+
+    /**
+     * SIP TF timer value in milliseconds.  See RFC 3261 for information.
+     * <p>
+     * The TF timer is the non-INVITE transaction timeout timer.
+     * <p>
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_TF_TIMER_VALUE_MS = 9;
+
+    /**
      * An integer key representing the voice over LTE (VoLTE) provisioning status for the
      * associated subscription. Determines whether the user can register for voice services over
      * LTE.
@@ -140,6 +257,43 @@
     public static final int KEY_VT_PROVISIONING_STATUS = 11;
 
     /**
+     * Domain Name for the device to populate the request URI for REGISTRATION.
+     * Value is in String format.
+     * @see #setProvisioningStringValue(int, String)
+     * @see #getProvisioningStringValue(int)
+     */
+    public static final int KEY_REGISTRATION_DOMAIN_NAME = 12;
+
+    /**
+     * Device Outgoing SMS based on either 3GPP or 3GPP2 standards.
+     * Value is in Integer format.
+     * Valid values are {@link #SMS_FORMAT_3GPP} and {@link #SMS_FORMAT_3GPP2}.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_SMS_FORMAT = 13;
+
+    /**
+     * Value used with {@link #KEY_SMS_FORMAT} to indicate 3GPP2 SMS format is used.
+     * See {@link android.telephony.SmsMessage#FORMAT_3GPP2} for more information.
+     */
+    public static final int SMS_FORMAT_3GPP2 = 0;
+
+    /**
+     * Value used with {@link #KEY_SMS_FORMAT} to indicate 3GPP SMS format is used.
+     * See {@link android.telephony.SmsMessage#FORMAT_3GPP} for more information.
+     */
+    public static final int SMS_FORMAT_3GPP = 1;
+
+    /**
+     * Turns SMS over IMS ON/OFF on the device.
+     * Value is in Integer format. ON (1), OFF(0).
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_SMS_OVER_IP_ENABLED = 14;
+
+    /**
      * An integer key associated with the carrier configured SIP PUBLISH timer, which dictates the
      * expiration time in seconds for published online availability in RCS presence.
      * <p>
@@ -222,7 +376,7 @@
     public static final int KEY_RCS_MAX_NUM_ENTRIES_IN_RCL = 22;
 
     /**
-     * An integer associated with the expiration timer used duriing the SIP subscription of a
+     * An integer associated with the expiration timer used during the SIP subscription of a
      * Request Contained List (RCL), which is used to retrieve the RCS capabilities of the contact
      * book.
      * <p>
@@ -233,6 +387,14 @@
     public static final int KEY_RCS_CAPABILITY_POLL_LIST_SUB_EXP_SEC = 23;
 
     /**
+     * Applies compression to LIST Subscription.
+     * Value is in Integer format. Enable (1), Disable(0).
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_USE_GZIP_FOR_LIST_SUBSCRIPTION = 24;
+
+    /**
      * An integer key representing the RCS enhanced address book (EAB) provisioning status for the
      * associated subscription. Determines whether or not SIP OPTIONS or presence will be used to
      * retrieve RCS capabilities for the user's contacts.
@@ -270,6 +432,349 @@
     public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27;
 
     /**
+     * Enable voice over wifi.  Enabled (1), or Disabled (0).
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE = 28;
+
+    /**
+     * Mobile data enabled.
+     * Value is in Integer format. On (1), OFF(0).
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_MOBILE_DATA_ENABLED = 29;
+
+    /**
+     * VoLTE user opted in status.
+     * Value is in Integer format. Opted-in (1) Opted-out (0).
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_VOLTE_USER_OPT_IN_STATUS = 30;
+
+    /**
+     * Proxy for Call Session Control Function(P-CSCF) address for Local-BreakOut(LBO).
+     * Value is in String format.
+     */
+    public static final int KEY_LOCAL_BREAKOUT_PCSCF_ADDRESS = 31;
+
+    /**
+     * Keep Alive Enabled for SIP.
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_SIP_KEEP_ALIVE_ENABLED = 32;
+
+    /**
+     * Registration retry Base Time value in seconds.
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_REGISTRATION_RETRY_BASE_TIME_SEC = 33;
+
+    /**
+     * Registration retry Max Time value in seconds.
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_REGISTRATION_RETRY_MAX_TIME_SEC = 34;
+
+    /**
+     * Smallest RTP port for speech codec.
+     * Value is in integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+
+    public static final int KEY_RTP_SPEECH_START_PORT = 35;
+
+    /**
+     * Largest RTP port for speech code.
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_RTP_SPEECH_END_PORT = 36;
+
+    /**
+     * SIP Timer A's value in milliseconds. Timer A is the INVITE request retransmit interval (in
+     * milliseconds), for UDP only.
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_SIP_INVITE_REQUEST_TRANSMIT_INTERVAL_MS = 37;
+
+    /**
+     * SIP Timer B's value in milliseconds. Timer B is the wait time for INVITE message to be,
+     * in milliseconds.
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_SIP_INVITE_ACK_WAIT_TIME_MS = 38;
+
+    /**
+     * SIP Timer D's value in milliseconds. Timer D is the wait time for response retransmits of
+     * the invite client transactions, in milliseconds.
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_SIP_INVITE_RESPONSE_RETRANSMIT_WAIT_TIME_MS = 39;
+
+    /**
+     * SIP Timer E's value in milliseconds. Timer E is the value Non-INVITE request retransmit
+     * interval (in milliseconds), for UDP only.
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_SIP_NON_INVITE_REQUEST_RETRANSMIT_INTERVAL_MS = 40;
+
+    /**
+     * SIP Timer F's value in milliseconds. Timer F is the Non-INVITE transaction timeout timer,
+     * in milliseconds.
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_SIP_NON_INVITE_TRANSACTION_TIMEOUT_TIMER_MS = 41;
+
+    /**
+     * SIP Timer G's value in milliseconds. Timer G is the value of INVITE response
+     * retransmit interval.
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_SIP_INVITE_RESPONSE_RETRANSMIT_INTERVAL_MS = 42;
+
+    /**
+     * SIP Timer H's value in milliseconds. Timer H is the value of wait time for
+     * ACK receipt.
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_SIP_ACK_RECEIPT_WAIT_TIME_MS = 43;
+
+    /**
+     * SIP Timer I's value in milliseconds. Timer I is the value of wait time for
+     * ACK retransmits.
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_SIP_ACK_RETRANSMIT_WAIT_TIME_MS = 44;
+
+    /**
+     * SIP Timer J's value in milliseconds. Timer J is the value of wait time for
+     * non-invite request retransmission.
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_SIP_NON_INVITE_REQUEST_RETRANSMISSION_WAIT_TIME_MS = 45;
+
+    /**
+     * SIP Timer K's value in milliseconds. Timer K is the value of wait time for
+     * non-invite response retransmits.
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_SIP_NON_INVITE_RESPONSE_RETRANSMISSION_WAIT_TIME_MS = 46;
+
+    /**
+     * AMR WB octet aligned dynamic payload type.
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_AMR_WB_OCTET_ALIGNED_PAYLOAD_TYPE = 47;
+
+    /**
+     * AMR WB bandwidth efficient payload type.
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_AMR_WB_BANDWIDTH_EFFICIENT_PAYLOAD_TYPE = 48;
+
+    /**
+     * AMR octet aligned dynamic payload type.
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_AMR_OCTET_ALIGNED_PAYLOAD_TYPE = 49;
+
+    /**
+     * AMR bandwidth efficient payload type.
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_AMR_BANDWIDTH_EFFICIENT_PAYLOAD_TYPE = 50;
+
+    /**
+     * DTMF WB payload type.
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_DTMF_WB_PAYLOAD_TYPE = 51;
+
+    /**
+     * DTMF NB payload type.
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_DTMF_NB_PAYLOAD_TYPE = 52;
+
+    /**
+     * AMR Default encoding mode.
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_AMR_DEFAULT_ENCODING_MODE = 53;
+
+    /**
+     * SMS Public Service Identity.
+     * Value is in String format.
+     */
+    public static final int KEY_SMS_PUBLIC_SERVICE_IDENTITY = 54;
+
+    /**
+     * Video Quality - VideoQualityFeatureValuesConstants.
+     * Valid values are: {@link #VIDEO_QUALITY_HIGH} and {@link #VIDEO_QUALITY_LOW}.
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_VIDEO_QUALITY = 55;
+
+    /**
+     * Used with {@link #KEY_VIDEO_QUALITY} to indicate low video quality.
+     */
+    public static final int VIDEO_QUALITY_LOW = 0;
+
+    /**
+     * Used with {@link #KEY_VIDEO_QUALITY} to indicate high video quality.
+     */
+    public static final int VIDEO_QUALITY_HIGH = 1;
+
+    /**
+     * LTE to WIFI handover threshold.
+     * Handover from LTE to WiFi if LTE < THLTE1 and WiFi >= {@link #KEY_WIFI_THRESHOLD_A}.
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_LTE_THRESHOLD_1 = 56;
+
+    /**
+     * WIFI to LTE handover threshold.
+     * Handover from WiFi to LTE if LTE >= {@link #KEY_LTE_THRESHOLD_3} or (WiFi < {@link
+     * #KEY_WIFI_THRESHOLD_B} and LTE >= {@link #KEY_LTE_THRESHOLD_2}).
+     * Value is in Integer format.
+     *
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_LTE_THRESHOLD_2 = 57;
+
+    /**
+     * LTE to WIFI handover threshold.
+     * Handover from WiFi to LTE if LTE >= {@link #KEY_LTE_THRESHOLD_3} or (WiFi < {@link
+     * #KEY_WIFI_THRESHOLD_B} and LTE >= {@link #KEY_LTE_THRESHOLD_2}).
+     * Value is in Integer format.
+     *
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_LTE_THRESHOLD_3 = 58;
+
+    /**
+     * 1x to WIFI handover threshold.
+     * Handover from 1x to WiFi if 1x < {@link #KEY_1X_THRESHOLD}.
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_1X_THRESHOLD = 59;
+
+    /**
+     * LTE to WIFI threshold A.
+     * Handover from LTE to WiFi if LTE < {@link #KEY_LTE_THRESHOLD_1} and WiFi >= {@link
+     * #KEY_WIFI_THRESHOLD_A}.
+     * Value is in Integer format.
+     *
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_WIFI_THRESHOLD_A = 60;
+
+    /**
+     * WiFi to LTRE handover threshold B.
+     * Handover from WiFi to LTE if LTE >= {@link #KEY_LTE_THRESHOLD_3} or (WiFi <
+     * {@link #KEY_WIFI_THRESHOLD_B} and LTE >= {@link #KEY_LTE_THRESHOLD_2}).
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_WIFI_THRESHOLD_B = 61;
+
+    /**
+     * LTE ePDG timer (in seconds).
+     * Device shall not handover back to LTE until the T_ePDG_LTE timer expires.
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_LTE_EPDG_TIMER_SEC = 62;
+
+    /**
+     * WiFi ePDG timer (in seconds).
+     * Device shall not handover back to WiFi until the T_ePDG_WiFi timer expires.
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_WIFI_EPDG_TIMER_SEC = 63;
+
+    /**
+     * 1x ePDG timer (in seconds).
+     * Device shall not re-register on 1x until the T_ePDG_1x timer expires.
+     */
+    public static final int KEY_1X_EPDG_TIMER_SEC = 64;
+
+    /**
+     * MultiEndpoint status: Enabled (1), or Disabled (0).
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_MULTIENDPOINT_ENABLED = 65;
+
+    /**
+     * RTT status: Enabled (1), or Disabled (0).
+     * Value is in Integer format.
+     * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     */
+    public static final int KEY_RTT_ENABLED = 66;
+
+    /**
      * Callback for IMS provisioning changes.
      */
     public static class Callback {
diff --git a/telephony/java/com/android/ims/ImsConfig.java b/telephony/java/com/android/ims/ImsConfig.java
index 0d86e2b..0f6ce13 100644
--- a/telephony/java/com/android/ims/ImsConfig.java
+++ b/telephony/java/com/android/ims/ImsConfig.java
@@ -135,374 +135,596 @@
         /**
          * AMR CODEC Mode Value set, 0-7 in comma separated sequence.
          * Value is in String format.
+         * @deprecated use {@link ProvisioningManager#KEY_AMR_CODEC_MODE_SET_VALUES} instead.
          */
-        public static final int VOCODER_AMRMODESET = CONFIG_START;
+        @Deprecated
+        public static final int VOCODER_AMRMODESET =
+                ProvisioningManager.KEY_AMR_CODEC_MODE_SET_VALUES;
 
         /**
          * Wide Band AMR CODEC Mode Value set,0-7 in comma separated sequence.
          * Value is in String format.
+         * @deprecated use {@link ProvisioningManager#KEY_AMR_WB_CODEC_MODE_SET_VALUES} instead.
          */
-        public static final int VOCODER_AMRWBMODESET = 1;
+        @Deprecated
+        public static final int VOCODER_AMRWBMODESET =
+                ProvisioningManager.KEY_AMR_WB_CODEC_MODE_SET_VALUES;
 
         /**
          * SIP Session Timer value (seconds).
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_SIP_SESSION_TIMER_SEC} instead.
          */
-        public static final int SIP_SESSION_TIMER = 2;
+        @Deprecated
+        public static final int SIP_SESSION_TIMER = ProvisioningManager.KEY_SIP_SESSION_TIMER_SEC;
 
         /**
          * Minimum SIP Session Expiration Timer in (seconds).
          * Value is in Integer format.
+         * @deprecated use
+         * {@link ProvisioningManager#KEY_MINIMUM_SIP_SESSION_EXPIRATION_TIMER_SEC} instead.
          */
-        public static final int MIN_SE = 3;
+        @Deprecated
+        public static final int MIN_SE =
+                ProvisioningManager.KEY_MINIMUM_SIP_SESSION_EXPIRATION_TIMER_SEC;
 
         /**
          * SIP_INVITE cancellation time out value (in milliseconds). Integer format.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_SIP_INVITE_CANCELLATION_TIMER_MS} instead.
          */
-        public static final int CANCELLATION_TIMER = 4;
+        @Deprecated
+        public static final int CANCELLATION_TIMER =
+                ProvisioningManager.KEY_SIP_INVITE_CANCELLATION_TIMER_MS;
 
         /**
          * Delay time when an iRAT transition from eHRPD/HRPD/1xRTT to LTE.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_TRANSITION_TO_LTE_DELAY_MS} instead.
          */
-        public static final int TDELAY = 5;
+        @Deprecated
+        public static final int TDELAY = ProvisioningManager.KEY_TRANSITION_TO_LTE_DELAY_MS;
 
         /**
          * Silent redial status of Enabled (True), or Disabled (False).
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_ENABLE_SILENT_REDIAL} instead.
          */
-        public static final int SILENT_REDIAL_ENABLE = 6;
+        @Deprecated
+        public static final int SILENT_REDIAL_ENABLE = ProvisioningManager.KEY_ENABLE_SILENT_REDIAL;
 
         /**
          * SIP T1 timer value in milliseconds. See RFC 3261 for define.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_T1_TIMER_VALUE_MS} instead.
          */
+        @Deprecated
         public static final int SIP_T1_TIMER = ProvisioningManager.KEY_T1_TIMER_VALUE_MS;
 
         /**
          * SIP T2 timer value in milliseconds.  See RFC 3261 for define.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_T2_TIMER_VALUE_MS} instead.
          */
-        public static final int SIP_T2_TIMER  = 8;
+        @Deprecated
+        public static final int SIP_T2_TIMER  = ProvisioningManager.KEY_T2_TIMER_VALUE_MS;
 
-         /**
+        /**
          * SIP TF timer value in milliseconds.  See RFC 3261 for define.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_TF_TIMER_VALUE_MS} instead.
          */
-        public static final int SIP_TF_TIMER = 9;
+        @Deprecated
+        public static final int SIP_TF_TIMER = ProvisioningManager.KEY_TF_TIMER_VALUE_MS;
 
         /**
          * VoLTE status for VLT/s status of Enabled (1), or Disabled (0).
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_VOLTE_PROVISIONING_STATUS} instead.
          */
+        @Deprecated
         public static final int VLT_SETTING_ENABLED =
                 ProvisioningManager.KEY_VOLTE_PROVISIONING_STATUS;
 
         /**
          * VoLTE status for LVC/s status of Enabled (1), or Disabled (0).
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_VT_PROVISIONING_STATUS} instead.
          */
+        @Deprecated
         public static final int LVC_SETTING_ENABLED =
                 ProvisioningManager.KEY_VT_PROVISIONING_STATUS;
+
         /**
          * Domain Name for the device to populate the request URI for REGISTRATION.
          * Value is in String format.
+         * @deprecated use {@link ProvisioningManager#KEY_REGISTRATION_DOMAIN_NAME}.
          */
-        public static final int DOMAIN_NAME = 12;
+        @Deprecated
+        public static final int DOMAIN_NAME = ProvisioningManager.KEY_REGISTRATION_DOMAIN_NAME;
+
          /**
          * Device Outgoing SMS based on either 3GPP or 3GPP2 standards.
          * Value is in Integer format. 3GPP2(0), 3GPP(1)
-         */
-        public static final int SMS_FORMAT = 13;
+          * @deprecated use {@link ProvisioningManager#KEY_SMS_FORMAT}.
+          */
+         @Deprecated
+         public static final int SMS_FORMAT = ProvisioningManager.KEY_SMS_FORMAT;
+
          /**
          * Turns IMS ON/OFF on the device.
          * Value is in Integer format. ON (1), OFF(0).
-         */
-        public static final int SMS_OVER_IP = 14;
+          * @deprecated use {@link ProvisioningManager#KEY_SMS_OVER_IP_ENABLED}.
+          */
+         @Deprecated
+         public static final int SMS_OVER_IP = ProvisioningManager.KEY_SMS_OVER_IP_ENABLED;
+
         /**
          * Requested expiration for Published Online availability.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_RCS_PUBLISH_TIMER_SEC}.
          */
+        @Deprecated
         public static final int PUBLISH_TIMER = ProvisioningManager.KEY_RCS_PUBLISH_TIMER_SEC;
+
         /**
          * Requested expiration for Published Offline availability.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_RCS_PUBLISH_TIMER_EXTENDED_SEC}.
          */
+        @Deprecated
         public static final int PUBLISH_TIMER_EXTENDED =
                 ProvisioningManager.KEY_RCS_PUBLISH_TIMER_EXTENDED_SEC;
+
         /**
          *
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_RCS_CAPABILITY_DISCOVERY_ENABLED}.
          */
+        @Deprecated
         public static final int CAPABILITY_DISCOVERY_ENABLED =
                 ProvisioningManager.KEY_RCS_CAPABILITY_DISCOVERY_ENABLED;
+
         /**
-         * Period of time the capability information of the  contact is cached on handset.
+         * Period of time the capability information of the contact is cached on handset.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC}.
          */
+        @Deprecated
         public static final int CAPABILITIES_CACHE_EXPIRATION =
                 ProvisioningManager.KEY_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC;
+
         /**
          * Peiod of time the availability information of a contact is cached on device.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_RCS_AVAILABILITY_CACHE_EXPIRATION_SEC}.
          */
+        @Deprecated
         public static final int AVAILABILITY_CACHE_EXPIRATION =
                 ProvisioningManager.KEY_RCS_AVAILABILITY_CACHE_EXPIRATION_SEC;
+
         /**
          * Interval between successive capabilities polling.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_RCS_CAPABILITIES_POLL_INTERVAL_SEC}.
          */
+        @Deprecated
         public static final int CAPABILITIES_POLL_INTERVAL =
                 ProvisioningManager.KEY_RCS_CAPABILITIES_POLL_INTERVAL_SEC;
+
         /**
          * Minimum time between two published messages from the device.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_RCS_PUBLISH_SOURCE_THROTTLE_MS}.
          */
+        @Deprecated
         public static final int SOURCE_THROTTLE_PUBLISH =
                 ProvisioningManager.KEY_RCS_PUBLISH_SOURCE_THROTTLE_MS;
+
         /**
          * The Maximum number of MDNs contained in one Request Contained List.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_RCS_MAX_NUM_ENTRIES_IN_RCL}.
          */
+        @Deprecated
         public static final int MAX_NUMENTRIES_IN_RCL =
                 ProvisioningManager.KEY_RCS_MAX_NUM_ENTRIES_IN_RCL;
+
         /**
          * Expiration timer for subscription of a Request Contained List, used in capability
          * polling.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_RCS_CAPABILITY_POLL_LIST_SUB_EXP_SEC}.
          */
+        @Deprecated
         public static final int CAPAB_POLL_LIST_SUB_EXP =
                 ProvisioningManager.KEY_RCS_CAPABILITY_POLL_LIST_SUB_EXP_SEC;
+
         /**
          * Applies compression to LIST Subscription.
          * Value is in Integer format. Enable (1), Disable(0).
+         * @deprecated use {@link ProvisioningManager#KEY_USE_GZIP_FOR_LIST_SUBSCRIPTION}.
          */
-        public static final int GZIP_FLAG = 24;
+        @Deprecated
+        public static final int GZIP_FLAG = ProvisioningManager.KEY_USE_GZIP_FOR_LIST_SUBSCRIPTION;
+
         /**
          * VOLTE Status for EAB/s status of Enabled (1), or Disabled (0).
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_EAB_PROVISIONING_STATUS}.
          */
+        @Deprecated
         public static final int EAB_SETTING_ENABLED =
                 ProvisioningManager.KEY_EAB_PROVISIONING_STATUS;
+
         /**
          * Wi-Fi calling roaming status.
          * Value is in Integer format. ON (1), OFF(0).
+         * @deprecated use {@link ProvisioningManager#KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE}
+         * instead.
          */
+        @Deprecated
         public static final int VOICE_OVER_WIFI_ROAMING =
                 ProvisioningManager.KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE;
+
         /**
-         * Wi-Fi calling modem - WfcModeFeatureValueConstants.
+         * Wi-Fi calling mode - WfcModeFeatureValueConstants.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_VOICE_OVER_WIFI_MODE_OVERRIDE}
+         * instead.
          */
+        @Deprecated
         public static final int VOICE_OVER_WIFI_MODE =
                 ProvisioningManager.KEY_VOICE_OVER_WIFI_MODE_OVERRIDE;
+
         /**
          * VOLTE Status for voice over wifi status of Enabled (1), or Disabled (0).
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE}.
          */
-        public static final int VOICE_OVER_WIFI_SETTING_ENABLED = 28;
+        @Deprecated
+        public static final int VOICE_OVER_WIFI_SETTING_ENABLED =
+                ProvisioningManager.KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE;
+
+
         /**
          * Mobile data enabled.
          * Value is in Integer format. On (1), OFF(0).
+         * @deprecated use {@link ProvisioningManager#KEY_MOBILE_DATA_ENABLED}.
          */
-        public static final int MOBILE_DATA_ENABLED = 29;
+        @Deprecated
+        public static final int MOBILE_DATA_ENABLED = ProvisioningManager.KEY_MOBILE_DATA_ENABLED;
+
         /**
          * VoLTE user opted in status.
          * Value is in Integer format. Opted-in (1) Opted-out (0).
+         * @deprecated use {@link ProvisioningManager#KEY_VOLTE_USER_OPT_IN_STATUS}.
          */
-        public static final int VOLTE_USER_OPT_IN_STATUS = 30;
+        @Deprecated
+        public static final int VOLTE_USER_OPT_IN_STATUS =
+                ProvisioningManager.KEY_VOLTE_USER_OPT_IN_STATUS;
+
         /**
          * Proxy for Call Session Control Function(P-CSCF) address for Local-BreakOut(LBO).
          * Value is in String format.
+         * @deprecated use {@link ProvisioningManager#KEY_LOCAL_BREAKOUT_PCSCF_ADDRESS}.
          */
-        public static final int LBO_PCSCF_ADDRESS = 31;
+        @Deprecated
+        public static final int LBO_PCSCF_ADDRESS =
+                ProvisioningManager.KEY_LOCAL_BREAKOUT_PCSCF_ADDRESS;
+
         /**
          * Keep Alive Enabled for SIP.
          * Value is in Integer format. On(1), OFF(0).
+         * @deprecated use {@link ProvisioningManager#KEY_SIP_KEEP_ALIVE_ENABLED}.
          */
-        public static final int KEEP_ALIVE_ENABLED = 32;
+        @Deprecated
+        public static final int KEEP_ALIVE_ENABLED = ProvisioningManager.KEY_SIP_KEEP_ALIVE_ENABLED;
+
         /**
          * Registration retry Base Time value in seconds.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_REGISTRATION_RETRY_BASE_TIME_SEC}.
          */
-        public static final int REGISTRATION_RETRY_BASE_TIME_SEC = 33;
+        @Deprecated
+        public static final int REGISTRATION_RETRY_BASE_TIME_SEC =
+                ProvisioningManager.KEY_REGISTRATION_RETRY_BASE_TIME_SEC;
+
         /**
          * Registration retry Max Time value in seconds.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_REGISTRATION_RETRY_MAX_TIME_SEC}.
          */
-        public static final int REGISTRATION_RETRY_MAX_TIME_SEC = 34;
+        @Deprecated
+        public static final int REGISTRATION_RETRY_MAX_TIME_SEC =
+                ProvisioningManager.KEY_REGISTRATION_RETRY_MAX_TIME_SEC;
+
         /**
          * Smallest RTP port for speech codec.
          * Value is in integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_RTP_SPEECH_START_PORT}.
          */
-        public static final int SPEECH_START_PORT = 35;
+        @Deprecated
+        public static final int SPEECH_START_PORT = ProvisioningManager.KEY_RTP_SPEECH_START_PORT;
+
         /**
          * Largest RTP port for speech code.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_RTP_SPEECH_END_PORT}.
          */
-        public static final int SPEECH_END_PORT = 36;
+        @Deprecated
+        public static final int SPEECH_END_PORT = ProvisioningManager.KEY_RTP_SPEECH_END_PORT;
+
         /**
          * SIP Timer A's value in milliseconds. Timer A is the INVITE request
          * retransmit interval, for UDP only.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_SIP_INVITE_REQUEST_TRANSMIT_INTERVAL_MS}.
          */
-        public static final int SIP_INVITE_REQ_RETX_INTERVAL_MSEC = 37;
+        @Deprecated
+        public static final int SIP_INVITE_REQ_RETX_INTERVAL_MSEC =
+                ProvisioningManager.KEY_SIP_INVITE_REQUEST_TRANSMIT_INTERVAL_MS;
+
         /**
          * SIP Timer B's value in milliseconds. Timer B is the wait time for
          * INVITE message to be acknowledged.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_SIP_INVITE_ACK_WAIT_TIME_MS}.
          */
-        public static final int SIP_INVITE_RSP_WAIT_TIME_MSEC = 38;
+        @Deprecated
+        public static final int SIP_INVITE_RSP_WAIT_TIME_MSEC =
+                ProvisioningManager.KEY_SIP_INVITE_ACK_WAIT_TIME_MS;
+
         /**
          * SIP Timer D's value in milliseconds. Timer D is the wait time for
          * response retransmits of the invite client transactions.
          * Value is in Integer format.
+         * @deprecated use
+         * {@link ProvisioningManager#KEY_SIP_INVITE_RESPONSE_RETRANSMIT_WAIT_TIME_MS}.
          */
-        public static final int SIP_INVITE_RSP_RETX_WAIT_TIME_MSEC = 39;
+        @Deprecated
+        public static final int SIP_INVITE_RSP_RETX_WAIT_TIME_MSEC =
+                ProvisioningManager.KEY_SIP_INVITE_RESPONSE_RETRANSMIT_WAIT_TIME_MS;
+
         /**
          * SIP Timer E's value in milliseconds. Timer E is the value Non-INVITE
          * request retransmit interval, for UDP only.
          * Value is in Integer format.
+         * @deprecated use
+         * {@link ProvisioningManager#KEY_SIP_NON_INVITE_REQUEST_RETRANSMIT_INTERVAL_MS}.
          */
-        public static final int SIP_NON_INVITE_REQ_RETX_INTERVAL_MSEC = 40;
+        @Deprecated
+        public static final int SIP_NON_INVITE_REQ_RETX_INTERVAL_MSEC =
+                ProvisioningManager.KEY_SIP_NON_INVITE_REQUEST_RETRANSMIT_INTERVAL_MS;
+
         /**
          * SIP Timer F's value in milliseconds. Timer F is the Non-INVITE transaction
          * timeout timer.
          * Value is in Integer format.
+         * @deprecated use
+         * {@link ProvisioningManager#KEY_SIP_NON_INVITE_TRANSACTION_TIMEOUT_TIMER_MS}.
          */
-        public static final int SIP_NON_INVITE_TXN_TIMEOUT_TIMER_MSEC = 41;
+        @Deprecated
+        public static final int SIP_NON_INVITE_TXN_TIMEOUT_TIMER_MSEC =
+                ProvisioningManager.KEY_SIP_NON_INVITE_TRANSACTION_TIMEOUT_TIMER_MS;
+
         /**
          * SIP Timer G's value in milliseconds. Timer G is the value of INVITE response
          * retransmit interval.
          * Value is in Integer format.
+         * @deprecated use
+         * {@link ProvisioningManager#KEY_SIP_INVITE_RESPONSE_RETRANSMIT_INTERVAL_MS}.
          */
-        public static final int SIP_INVITE_RSP_RETX_INTERVAL_MSEC = 42;
+        @Deprecated
+        public static final int SIP_INVITE_RSP_RETX_INTERVAL_MSEC =
+                ProvisioningManager.KEY_SIP_INVITE_RESPONSE_RETRANSMIT_INTERVAL_MS;
+
         /**
          * SIP Timer H's value in milliseconds. Timer H is the value of wait time for
          * ACK receipt.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_SIP_ACK_RECEIPT_WAIT_TIME_MS}.
          */
-        public static final int SIP_ACK_RECEIPT_WAIT_TIME_MSEC = 43;
+        @Deprecated
+        public static final int SIP_ACK_RECEIPT_WAIT_TIME_MSEC =
+                ProvisioningManager.KEY_SIP_ACK_RECEIPT_WAIT_TIME_MS;
+
         /**
          * SIP Timer I's value in milliseconds. Timer I is the value of wait time for
          * ACK retransmits.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_SIP_ACK_RETRANSMIT_WAIT_TIME_MS}.
          */
-        public static final int SIP_ACK_RETX_WAIT_TIME_MSEC = 44;
+        @Deprecated
+        public static final int SIP_ACK_RETX_WAIT_TIME_MSEC =
+                ProvisioningManager.KEY_SIP_ACK_RETRANSMIT_WAIT_TIME_MS;
+
         /**
          * SIP Timer J's value in milliseconds. Timer J is the value of wait time for
          * non-invite request retransmission.
          * Value is in Integer format.
+         * @deprecated use
+         * {@link ProvisioningManager#KEY_SIP_NON_INVITE_REQUEST_RETRANSMISSION_WAIT_TIME_MS}.
          */
-        public static final int SIP_NON_INVITE_REQ_RETX_WAIT_TIME_MSEC = 45;
+        @Deprecated
+        public static final int SIP_NON_INVITE_REQ_RETX_WAIT_TIME_MSEC =
+                ProvisioningManager.KEY_SIP_NON_INVITE_REQUEST_RETRANSMISSION_WAIT_TIME_MS;
+
         /**
          * SIP Timer K's value in milliseconds. Timer K is the value of wait time for
          * non-invite response retransmits.
          * Value is in Integer format.
+         * @deprecated use
+         * {@link ProvisioningManager#KEY_SIP_NON_INVITE_RESPONSE_RETRANSMISSION_WAIT_TIME_MS}.
          */
-        public static final int SIP_NON_INVITE_RSP_RETX_WAIT_TIME_MSEC = 46;
+        @Deprecated
+        public static final int SIP_NON_INVITE_RSP_RETX_WAIT_TIME_MSEC =
+                ProvisioningManager.KEY_SIP_NON_INVITE_RESPONSE_RETRANSMISSION_WAIT_TIME_MS;
+
         /**
          * AMR WB octet aligned dynamic payload type.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_AMR_WB_OCTET_ALIGNED_PAYLOAD_TYPE}.
          */
-        public static final int AMR_WB_OCTET_ALIGNED_PT = 47;
+        @Deprecated
+        public static final int AMR_WB_OCTET_ALIGNED_PT =
+                ProvisioningManager.KEY_AMR_WB_OCTET_ALIGNED_PAYLOAD_TYPE;
+
         /**
          * AMR WB bandwidth efficient payload type.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_AMR_WB_BANDWIDTH_EFFICIENT_PAYLOAD_TYPE}.
          */
-        public static final int AMR_WB_BANDWIDTH_EFFICIENT_PT = 48;
+        @Deprecated
+        public static final int AMR_WB_BANDWIDTH_EFFICIENT_PT =
+                ProvisioningManager.KEY_AMR_WB_BANDWIDTH_EFFICIENT_PAYLOAD_TYPE;
+
         /**
          * AMR octet aligned dynamic payload type.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_AMR_OCTET_ALIGNED_PAYLOAD_TYPE}.
          */
-        public static final int AMR_OCTET_ALIGNED_PT = 49;
+        @Deprecated
+        public static final int AMR_OCTET_ALIGNED_PT =
+                ProvisioningManager.KEY_AMR_OCTET_ALIGNED_PAYLOAD_TYPE;
+
         /**
          * AMR bandwidth efficient payload type.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_AMR_BANDWIDTH_EFFICIENT_PAYLOAD_TYPE}.
          */
-        public static final int AMR_BANDWIDTH_EFFICIENT_PT = 50;
+        @Deprecated
+        public static final int AMR_BANDWIDTH_EFFICIENT_PT =
+                ProvisioningManager.KEY_AMR_BANDWIDTH_EFFICIENT_PAYLOAD_TYPE;
+
         /**
          * DTMF WB payload type.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_DTMF_WB_PAYLOAD_TYPE}.
          */
-        public static final int DTMF_WB_PT = 51;
+        @Deprecated
+        public static final int DTMF_WB_PT = ProvisioningManager.KEY_DTMF_WB_PAYLOAD_TYPE;
+
         /**
          * DTMF NB payload type.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_DTMF_NB_PAYLOAD_TYPE}.
          */
-        public static final int DTMF_NB_PT = 52;
+        @Deprecated
+        public static final int DTMF_NB_PT = ProvisioningManager.KEY_DTMF_NB_PAYLOAD_TYPE;
+
         /**
          * AMR Default encoding mode.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_AMR_DEFAULT_ENCODING_MODE}.
          */
-        public static final int AMR_DEFAULT_MODE = 53;
+        @Deprecated
+        public static final int AMR_DEFAULT_MODE =
+                ProvisioningManager.KEY_AMR_DEFAULT_ENCODING_MODE;
+
         /**
          * SMS Public Service Identity.
          * Value is in String format.
+         * @deprecated use {@link ProvisioningManager#KEY_SMS_PUBLIC_SERVICE_IDENTITY}.
          */
-        public static final int SMS_PSI = 54;
+        @Deprecated
+        public static final int SMS_PSI = ProvisioningManager.KEY_SMS_PUBLIC_SERVICE_IDENTITY;
+
         /**
          * Video Quality - VideoQualityFeatureValuesConstants.
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_VIDEO_QUALITY}.
          */
-        public static final int VIDEO_QUALITY = 55;
+        @Deprecated
+        public static final int VIDEO_QUALITY = ProvisioningManager.KEY_VIDEO_QUALITY;
+
         /**
          * LTE threshold.
          * Handover from LTE to WiFi if LTE < THLTE1 and WiFi >= VOWT_A.
+         * @deprecated use {@link ProvisioningManager#KEY_LTE_THRESHOLD_1}.
          */
-        public static final int TH_LTE1 = 56;
+        @Deprecated
+        public static final int TH_LTE1 = ProvisioningManager.KEY_LTE_THRESHOLD_1;
+
         /**
          * LTE threshold.
          * Handover from WiFi to LTE if LTE >= THLTE3 or (WiFi < VOWT_B and LTE >= THLTE2).
+         * @deprecated use {@link ProvisioningManager#KEY_LTE_THRESHOLD_2}.
          */
-        public static final int TH_LTE2 = 57;
+        @Deprecated
+        public static final int TH_LTE2 = ProvisioningManager.KEY_LTE_THRESHOLD_2;
+
         /**
          * LTE threshold.
          * Handover from WiFi to LTE if LTE >= THLTE3 or (WiFi < VOWT_B and LTE >= THLTE2).
+         * @deprecated use {@link ProvisioningManager#KEY_LTE_THRESHOLD_3}.
          */
-        public static final int TH_LTE3 = 58;
+        @Deprecated
+        public static final int TH_LTE3 = ProvisioningManager.KEY_LTE_THRESHOLD_3;
+
         /**
          * 1x threshold.
          * Handover from 1x to WiFi if 1x < TH1x
+         * @deprecated use {@link ProvisioningManager#KEY_1X_THRESHOLD}.
          */
-        public static final int TH_1x = 59;
+        @Deprecated
+        public static final int TH_1x = ProvisioningManager.KEY_1X_THRESHOLD;
+
         /**
          * WiFi threshold.
          * Handover from LTE to WiFi if LTE < THLTE1 and WiFi >= VOWT_A.
+         * @deprecated use {@link ProvisioningManager#KEY_WIFI_THRESHOLD_A}.
          */
-        public static final int VOWT_A = 60;
+        @Deprecated
+        public static final int VOWT_A = ProvisioningManager.KEY_WIFI_THRESHOLD_A;
+
         /**
          * WiFi threshold.
          * Handover from WiFi to LTE if LTE >= THLTE3 or (WiFi < VOWT_B and LTE >= THLTE2).
+         * @deprecated use {@link ProvisioningManager#KEY_WIFI_THRESHOLD_B}.
          */
-        public static final int VOWT_B = 61;
+        @Deprecated
+        public static final int VOWT_B = ProvisioningManager.KEY_WIFI_THRESHOLD_B;
+
         /**
          * LTE ePDG timer.
          * Device shall not handover back to LTE until the T_ePDG_LTE timer expires.
+         * @deprecated use {@link ProvisioningManager#KEY_LTE_EPDG_TIMER_SEC}.
          */
-        public static final int T_EPDG_LTE = 62;
+        @Deprecated
+        public static final int T_EPDG_LTE = ProvisioningManager.KEY_LTE_EPDG_TIMER_SEC;
+
         /**
          * WiFi ePDG timer.
          * Device shall not handover back to WiFi until the T_ePDG_WiFi timer expires.
+         * @deprecated use {@link ProvisioningManager#KEY_WIFI_EPDG_TIMER_SEC}.
          */
-        public static final int T_EPDG_WIFI = 63;
+        @Deprecated
+        public static final int T_EPDG_WIFI = ProvisioningManager.KEY_WIFI_EPDG_TIMER_SEC;
+
         /**
          * 1x ePDG timer.
          * Device shall not re-register on 1x until the T_ePDG_1x timer expires.
+         * @deprecated use {@link ProvisioningManager#KEY_1X_EPDG_TIMER_SEC}.
          */
-        public static final int T_EPDG_1X = 64;
+        @Deprecated
+        public static final int T_EPDG_1X = ProvisioningManager.KEY_1X_EPDG_TIMER_SEC;
+
         /**
          * MultiEndpoint status: Enabled (1), or Disabled (0).
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_MULTIENDPOINT_ENABLED}.
          */
-        public static final int VICE_SETTING_ENABLED = 65;
+        @Deprecated
+        public static final int VICE_SETTING_ENABLED = ProvisioningManager.KEY_MULTIENDPOINT_ENABLED;
 
         /**
          * RTT status: Enabled (1), or Disabled (0).
          * Value is in Integer format.
+         * @deprecated use {@link ProvisioningManager#KEY_RTT_ENABLED}.
          */
-        public static final int RTT_SETTING_ENABLED = 66;
+        @Deprecated
+        public static final int RTT_SETTING_ENABLED = ProvisioningManager.KEY_RTT_ENABLED;
 
         // Expand the operator config items as needed here, need to change
         // PROVISIONED_CONFIG_END after that.
diff --git a/telephony/java/com/android/internal/telephony/IBooleanConsumer.aidl b/telephony/java/com/android/internal/telephony/IBooleanConsumer.aidl
new file mode 100644
index 0000000..eb5beda
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IBooleanConsumer.aidl
@@ -0,0 +1,23 @@
+/*
+ * 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.telephony;
+
+// Copies consumer pattern for an operation that requires a boolean result from another process to
+// finish.
+oneway interface IBooleanConsumer {
+    void accept(boolean result);
+}
\ No newline at end of file
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index e88c773..9b45539 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -38,8 +38,10 @@
 import android.telephony.ModemActivityInfo;
 import android.telephony.NeighboringCellInfo;
 import android.telephony.NetworkScanRequest;
+import android.telephony.PhoneCapability;
 import android.telephony.PhoneNumberRange;
 import android.telephony.RadioAccessFamily;
+import android.telephony.RadioAccessSpecifier;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.TelephonyHistogram;
@@ -54,6 +56,7 @@
 import android.telephony.ims.aidl.IImsRegistrationCallback;
 import com.android.ims.internal.IImsServiceFeatureCallback;
 import com.android.internal.telephony.CellNetworkScanResult;
+import com.android.internal.telephony.IBooleanConsumer;
 import com.android.internal.telephony.IIntegerConsumer;
 import com.android.internal.telephony.INumberVerificationCallback;
 import com.android.internal.telephony.OperatorInfo;
@@ -1825,12 +1828,17 @@
     /**
      * Return the network selection mode on the subscription with id {@code subId}.
      */
-     int getNetworkSelectionMode(int subId);
+    int getNetworkSelectionMode(int subId);
 
-     /**
+    /**
+     * Return the PhoneCapability for the device.
+     */
+    PhoneCapability getPhoneCapability(int subId, String callingPackage, String callingFeatureId);
+
+    /**
      * Return true if the device is in emergency sms mode, false otherwise.
      */
-     boolean isInEmergencySmsMode();
+    boolean isInEmergencySmsMode();
 
     /**
      * Return the modem radio power state for slot index.
@@ -2126,6 +2134,9 @@
 
     boolean isApnMetered(int apnType, int subId);
 
+    oneway void setSystemSelectionChannels(in List<RadioAccessSpecifier> specifiers,
+            int subId, IBooleanConsumer resultCallback);
+
     boolean isMvnoMatched(int subId, int mvnoType, String mvnoMatchData);
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 9ee26c2..0db86d6 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -493,6 +493,7 @@
     int RIL_REQUEST_SWITCH_DUAL_SIM_CONFIG = 207;
     int RIL_REQUEST_ENABLE_UICC_APPLICATIONS = 208;
     int RIL_REQUEST_GET_UICC_APPLICATIONS_ENABLEMENT = 209;
+    int RIL_REQUEST_SET_SYSTEM_SELECTION_CHANNELS = 210;
 
     /* Responses begin */
     int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;
diff --git a/tests/net/common/java/android/net/LinkPropertiesTest.java b/tests/net/common/java/android/net/LinkPropertiesTest.java
index 6005cc3..f25fd4d 100644
--- a/tests/net/common/java/android/net/LinkPropertiesTest.java
+++ b/tests/net/common/java/android/net/LinkPropertiesTest.java
@@ -75,6 +75,9 @@
     private static final LinkAddress LINKADDRV4 = new LinkAddress(ADDRV4, 32);
     private static final LinkAddress LINKADDRV6 = new LinkAddress(ADDRV6, 128);
     private static final LinkAddress LINKADDRV6LINKLOCAL = new LinkAddress("fe80::1/64");
+    private static final Uri CAPPORT_API_URL = Uri.parse("https://test.example.com/capportapi");
+    private static final CaptivePortalData CAPPORT_DATA = new CaptivePortalData.Builder()
+            .setVenueInfoUrl(Uri.parse("https://test.example.com/venue")).build();
 
     private static InetAddress address(String addrString) {
         return InetAddresses.parseNumericAddress(addrString);
@@ -101,6 +104,8 @@
         assertFalse(lp.isIpv6Provisioned());
         assertFalse(lp.isPrivateDnsActive());
         assertFalse(lp.isWakeOnLanSupported());
+        assertNull(lp.getCaptivePortalApiUrl());
+        assertNull(lp.getCaptivePortalData());
     }
 
     private LinkProperties makeTestObject() {
@@ -124,6 +129,8 @@
         lp.setNat64Prefix(new IpPrefix("2001:db8:0:64::/96"));
         lp.setDhcpServerAddress(DHCPSERVER);
         lp.setWakeOnLanSupported(true);
+        lp.setCaptivePortalApiUrl(CAPPORT_API_URL);
+        lp.setCaptivePortalData(CAPPORT_DATA);
         return lp;
     }
 
@@ -165,6 +172,12 @@
         assertTrue(source.isIdenticalWakeOnLan(target));
         assertTrue(target.isIdenticalWakeOnLan(source));
 
+        assertTrue(source.isIdenticalCaptivePortalApiUrl(target));
+        assertTrue(target.isIdenticalCaptivePortalApiUrl(source));
+
+        assertTrue(source.isIdenticalCaptivePortalData(target));
+        assertTrue(target.isIdenticalCaptivePortalData(source));
+
         // Check result of equals().
         assertTrue(source.equals(target));
         assertTrue(target.equals(source));
@@ -963,6 +976,8 @@
         source.setNat64Prefix(new IpPrefix("2001:db8:1:2:64:64::/96"));
 
         source.setWakeOnLanSupported(true);
+        source.setCaptivePortalApiUrl(CAPPORT_API_URL);
+        source.setCaptivePortalData(CAPPORT_DATA);
 
         source.setDhcpServerAddress((Inet4Address) GATEWAY1);
 
@@ -970,7 +985,13 @@
         stacked.setInterfaceName("test-stacked");
         source.addStackedLink(stacked);
 
-        assertParcelSane(source, 16 /* fieldCount */);
+        assertParcelSane(source.makeSensitiveFieldsParcelingCopy(), 18 /* fieldCount */);
+
+        // Verify that without using a sensitiveFieldsParcelingCopy, sensitive fields are cleared.
+        final LinkProperties sanitized = new LinkProperties(source);
+        sanitized.setCaptivePortalApiUrl(null);
+        sanitized.setCaptivePortalData(null);
+        assertEquals(sanitized, parcelingRoundTrip(source));
     }
 
     @Test
@@ -1113,4 +1134,22 @@
         lp.clear();
         assertFalse(lp.isWakeOnLanSupported());
     }
+
+    @Test
+    public void testCaptivePortalApiUrl() {
+        final LinkProperties lp = makeTestObject();
+        assertEquals(CAPPORT_API_URL, lp.getCaptivePortalApiUrl());
+
+        lp.clear();
+        assertNull(lp.getCaptivePortalApiUrl());
+    }
+
+    @Test
+    public void testCaptivePortalData() {
+        final LinkProperties lp = makeTestObject();
+        assertEquals(CAPPORT_DATA, lp.getCaptivePortalData());
+
+        lp.clear();
+        assertNull(lp.getCaptivePortalData());
+    }
 }
diff --git a/tests/net/common/java/android/net/RouteInfoTest.java b/tests/net/common/java/android/net/RouteInfoTest.java
index 5ce8436..fe51b3a 100644
--- a/tests/net/common/java/android/net/RouteInfoTest.java
+++ b/tests/net/common/java/android/net/RouteInfoTest.java
@@ -258,6 +258,16 @@
         assertParcelingIsLossless(r);
 
         r = new RouteInfo(Prefix("192.0.2.0/24"), null, "wlan0");
-        assertParcelSane(r, 6);
+        assertParcelSane(r, 7);
+    }
+
+    public void testMtu() {
+        RouteInfo r;
+        r = new RouteInfo(Prefix("0.0.0.0/0"), Address("0.0.0.0"), "wlan0",
+                RouteInfo.RTN_UNICAST, 1500);
+        assertEquals(1500, r.getMtu());
+
+        r = new RouteInfo(Prefix("0.0.0.0/0"), Address("0.0.0.0"), "wlan0");
+        assertEquals(0, r.getMtu());
     }
 }
diff --git a/tests/net/java/android/net/CaptivePortalDataTest.kt b/tests/net/java/android/net/CaptivePortalDataTest.kt
new file mode 100644
index 0000000..0071438
--- /dev/null
+++ b/tests/net/java/android/net/CaptivePortalDataTest.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2019 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 android.net
+
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.testutils.assertParcelSane
+import com.android.testutils.assertParcelingIsLossless
+import org.junit.Test
+import org.junit.runner.RunWith
+import kotlin.test.assertEquals
+import kotlin.test.assertNotEquals
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class CaptivePortalDataTest {
+    private val data = CaptivePortalData.Builder()
+            .setRefreshTime(123L)
+            .setUserPortalUrl(Uri.parse("https://portal.example.com/test"))
+            .setVenueInfoUrl(Uri.parse("https://venue.example.com/test"))
+            .setSessionExtendable(true)
+            .setBytesRemaining(456L)
+            .setExpiryTime(789L)
+            .setCaptive(true)
+            .build()
+
+    private fun makeBuilder() = CaptivePortalData.Builder(data)
+
+    @Test
+    fun testParcelUnparcel() {
+        assertParcelSane(data, fieldCount = 7)
+
+        assertParcelingIsLossless(makeBuilder().setUserPortalUrl(null).build())
+        assertParcelingIsLossless(makeBuilder().setVenueInfoUrl(null).build())
+    }
+
+    @Test
+    fun testEquals() {
+        assertEquals(data, makeBuilder().build())
+
+        assertNotEqualsAfterChange { it.setRefreshTime(456L) }
+        assertNotEqualsAfterChange { it.setUserPortalUrl(Uri.parse("https://example.com/")) }
+        assertNotEqualsAfterChange { it.setUserPortalUrl(null) }
+        assertNotEqualsAfterChange { it.setVenueInfoUrl(Uri.parse("https://example.com/")) }
+        assertNotEqualsAfterChange { it.setVenueInfoUrl(null) }
+        assertNotEqualsAfterChange { it.setSessionExtendable(false) }
+        assertNotEqualsAfterChange { it.setBytesRemaining(789L) }
+        assertNotEqualsAfterChange { it.setExpiryTime(12L) }
+        assertNotEqualsAfterChange { it.setCaptive(false) }
+    }
+
+    private fun CaptivePortalData.mutate(mutator: (CaptivePortalData.Builder) -> Unit) =
+            CaptivePortalData.Builder(this).apply { mutator(this) }.build()
+
+    private fun assertNotEqualsAfterChange(mutator: (CaptivePortalData.Builder) -> Unit) {
+        assertNotEquals(data, data.mutate(mutator))
+    }
+}
\ No newline at end of file
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 4e29334..09cc69e 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -21,6 +21,8 @@
 import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
 import static android.content.pm.PackageManager.GET_PERMISSIONS;
 import static android.content.pm.PackageManager.MATCH_ANY_USER;
+import static android.content.pm.PackageManager.PERMISSION_DENIED;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN;
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_SUPL;
@@ -114,6 +116,7 @@
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
+import android.Manifest;
 import android.annotation.NonNull;
 import android.app.AlarmManager;
 import android.app.NotificationManager;
@@ -129,6 +132,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
+import android.net.CaptivePortalData;
 import android.net.ConnectivityManager;
 import android.net.ConnectivityManager.NetworkCallback;
 import android.net.ConnectivityManager.PacketKeepalive;
@@ -165,6 +169,7 @@
 import android.net.RouteInfo;
 import android.net.SocketKeepalive;
 import android.net.UidRange;
+import android.net.Uri;
 import android.net.metrics.IpConnectivityLog;
 import android.net.shared.NetworkMonitorUtils;
 import android.net.shared.PrivateDnsConfig;
@@ -243,8 +248,10 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
@@ -347,6 +354,8 @@
 
         @Spy private Resources mResources;
         private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
+        // Map of permission name -> PermissionManager.Permission_{GRANTED|DENIED} constant
+        private final HashMap<String, Integer> mMockedPermissions = new HashMap<>();
 
         MockContext(Context base, ContentProvider settingsProvider) {
             super(base);
@@ -417,13 +426,39 @@
         }
 
         @Override
+        public int checkPermission(String permission, int pid, int uid) {
+            final Integer granted = mMockedPermissions.get(permission);
+            if (granted == null) {
+                // All non-mocked permissions should be held by the test or unnecessary: check as
+                // normal to make sure the code does not rely on unexpected permissions.
+                return super.checkPermission(permission, pid, uid);
+            }
+            return granted;
+        }
+
+        @Override
         public void enforceCallingOrSelfPermission(String permission, String message) {
-            // The mainline permission can only be held if signed with the network stack certificate
-            // Skip testing for this permission.
-            if (NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK.equals(permission)) return;
-            // All other permissions should be held by the test or unnecessary: check as normal to
-            // make sure the code does not rely on unexpected permissions.
-            super.enforceCallingOrSelfPermission(permission, message);
+            final Integer granted = mMockedPermissions.get(permission);
+            if (granted == null) {
+                super.enforceCallingOrSelfPermission(permission, message);
+                return;
+            }
+
+            if (!granted.equals(PERMISSION_GRANTED)) {
+                throw new SecurityException("[Test] permission denied: " + permission);
+            }
+        }
+
+        /**
+         * Mock checks for the specified permission, and have them behave as per {@code granted}.
+         *
+         * <p>Passing null reverts to default behavior, which does a real permission check on the
+         * test package.
+         * @param granted One of {@link PackageManager#PERMISSION_GRANTED} or
+         *                {@link PackageManager#PERMISSION_DENIED}.
+         */
+        public void setPermission(String permission, Integer granted) {
+            mMockedPermissions.put(permission, granted);
         }
 
         @Override
@@ -1750,6 +1785,66 @@
         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
     }
 
+    private void doNetworkCallbacksSanitizationTest(boolean sanitized) throws Exception {
+        final TestNetworkCallback callback = new TestNetworkCallback();
+        final TestNetworkCallback defaultCallback = new TestNetworkCallback();
+        final NetworkRequest wifiRequest = new NetworkRequest.Builder()
+                .addTransportType(TRANSPORT_WIFI).build();
+        mCm.registerNetworkCallback(wifiRequest, callback);
+        mCm.registerDefaultNetworkCallback(defaultCallback);
+
+        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiNetworkAgent.connect(false);
+        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+
+        final LinkProperties newLp = new LinkProperties();
+        final Uri capportUrl = Uri.parse("https://capport.example.com/api");
+        final CaptivePortalData capportData = new CaptivePortalData.Builder()
+                .setCaptive(true).build();
+        newLp.setCaptivePortalApiUrl(capportUrl);
+        newLp.setCaptivePortalData(capportData);
+        mWiFiNetworkAgent.sendLinkProperties(newLp);
+
+        final Uri expectedCapportUrl = sanitized ? null : capportUrl;
+        final CaptivePortalData expectedCapportData = sanitized ? null : capportData;
+        callback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
+                Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl())
+                && Objects.equals(expectedCapportData, lp.getCaptivePortalData()));
+        defaultCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
+                Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl())
+                && Objects.equals(expectedCapportData, lp.getCaptivePortalData()));
+
+        final LinkProperties lp = mCm.getLinkProperties(mWiFiNetworkAgent.getNetwork());
+        assertEquals(expectedCapportUrl, lp.getCaptivePortalApiUrl());
+        assertEquals(expectedCapportData, lp.getCaptivePortalData());
+    }
+
+    @Test
+    public void networkCallbacksSanitizationTest_Sanitize() throws Exception {
+        mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+                PERMISSION_DENIED);
+        mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS,
+                PERMISSION_DENIED);
+        doNetworkCallbacksSanitizationTest(true /* sanitized */);
+    }
+
+    @Test
+    public void networkCallbacksSanitizationTest_NoSanitize_NetworkStack() throws Exception {
+        mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+                PERMISSION_GRANTED);
+        mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS, PERMISSION_DENIED);
+        doNetworkCallbacksSanitizationTest(false /* sanitized */);
+    }
+
+    @Test
+    public void networkCallbacksSanitizationTest_NoSanitize_Settings() throws Exception {
+        mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+                PERMISSION_DENIED);
+        mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED);
+        doNetworkCallbacksSanitizationTest(false /* sanitized */);
+    }
+
     @Test
     public void testMultipleLingering() throws Exception {
         // This test would be flaky with the default 120ms timer: that is short enough that
@@ -2628,6 +2723,8 @@
         final String testKey = "testkey";
         final String testValue = "testvalue";
         testBundle.putString(testKey, testValue);
+        mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+                PERMISSION_GRANTED);
         mCm.startCaptivePortalApp(wifiNetwork, testBundle);
         final Intent signInIntent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
         assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, signInIntent.getAction());
diff --git a/wifi/java/android/net/wifi/rtt/ResponderLocation.java b/wifi/java/android/net/wifi/rtt/ResponderLocation.java
index 970a75d..218b2dc 100644
--- a/wifi/java/android/net/wifi/rtt/ResponderLocation.java
+++ b/wifi/java/android/net/wifi/rtt/ResponderLocation.java
@@ -21,6 +21,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.location.Address;
 import android.location.Location;
@@ -1367,7 +1368,8 @@
      *
      */
     @Nullable
-    public SparseArray toCivicLocationSparseArray() {
+    @SuppressLint("ChangedType")
+    public SparseArray<String> toCivicLocationSparseArray() {
         if (mCivicLocation != null && mCivicLocation.isValid()) {
             return mCivicLocation.toSparseArray();
         } else {
diff --git a/wifi/tests/src/android/net/wifi/rtt/ResponderLocationTest.java b/wifi/tests/src/android/net/wifi/rtt/ResponderLocationTest.java
index b02eebb..271339c 100644
--- a/wifi/tests/src/android/net/wifi/rtt/ResponderLocationTest.java
+++ b/wifi/tests/src/android/net/wifi/rtt/ResponderLocationTest.java
@@ -20,6 +20,7 @@
 import android.location.Location;
 import android.net.MacAddress;
 import android.os.Parcel;
+import android.util.SparseArray;
 import android.webkit.MimeTypeMap;
 
 import static junit.framework.Assert.assertEquals;
@@ -505,6 +506,30 @@
     }
 
     /**
+     * Test that a Civic Location sparseArray can be extracted from a valid lcr buffer.
+     */
+    @Test
+    public void testLcrTestCivicLocationSparseArray() {
+        byte[] testLciBuffer = concatenateArrays(sTestLciIeHeader, sTestLciSE);
+        byte[] testLcrBuffer =
+                concatenateArrays(sTestLcrBufferHeader, sTestCivicLocationSEWithAddress);
+        ResponderLocation responderLocation = new ResponderLocation(testLciBuffer, testLcrBuffer);
+
+        boolean valid = responderLocation.isValid();
+        SparseArray<String> civicLocationSparseArray = responderLocation
+                .toCivicLocationSparseArray();
+
+        assertTrue(valid);
+        assertEquals("15", civicLocationSparseArray.get(CivicLocationKeys.HNO));
+        assertEquals("Alto",
+                civicLocationSparseArray.get(CivicLocationKeys.PRIMARY_ROAD_NAME));
+        assertEquals("Road",
+                civicLocationSparseArray.get(CivicLocationKeys.STREET_NAME_POST_MODIFIER));
+        assertEquals("Mtn View", civicLocationSparseArray.get(CivicLocationKeys.CITY));
+        assertEquals("94043", civicLocationSparseArray.get(CivicLocationKeys.POSTAL_CODE));
+    }
+
+    /**
      * Test that a URL can be extracted from a valid lcr buffer with a map image subelement.
      */
     @Test