Merge "[Telephony Mainline] Expose getActiveSubscriptionIdList"
diff --git a/Android.bp b/Android.bp
index 25c643d..0d07829 100644
--- a/Android.bp
+++ b/Android.bp
@@ -284,7 +284,7 @@
     name: "framework-aidl-export-defaults",
     aidl: {
         export_include_dirs: [
-            "apex/media/java",
+            "apex/media/framework/java",
             "core/java",
             "drm/java",
             "graphics/java",
diff --git a/apex/media/Android.bp b/apex/media/framework/Android.bp
similarity index 100%
rename from apex/media/Android.bp
rename to apex/media/framework/Android.bp
diff --git a/apex/media/jarjar_rules.txt b/apex/media/framework/jarjar_rules.txt
similarity index 100%
rename from apex/media/jarjar_rules.txt
rename to apex/media/framework/jarjar_rules.txt
diff --git a/apex/media/java/android/media/BufferingParams.java b/apex/media/framework/java/android/media/BufferingParams.java
similarity index 100%
rename from apex/media/java/android/media/BufferingParams.java
rename to apex/media/framework/java/android/media/BufferingParams.java
diff --git a/apex/media/java/android/media/Controller2Link.aidl b/apex/media/framework/java/android/media/Controller2Link.aidl
similarity index 100%
rename from apex/media/java/android/media/Controller2Link.aidl
rename to apex/media/framework/java/android/media/Controller2Link.aidl
diff --git a/apex/media/java/android/media/Controller2Link.java b/apex/media/framework/java/android/media/Controller2Link.java
similarity index 100%
rename from apex/media/java/android/media/Controller2Link.java
rename to apex/media/framework/java/android/media/Controller2Link.java
diff --git a/apex/media/java/android/media/DataSourceCallback.java b/apex/media/framework/java/android/media/DataSourceCallback.java
similarity index 100%
rename from apex/media/java/android/media/DataSourceCallback.java
rename to apex/media/framework/java/android/media/DataSourceCallback.java
diff --git a/apex/media/java/android/media/IMediaController2.aidl b/apex/media/framework/java/android/media/IMediaController2.aidl
similarity index 100%
rename from apex/media/java/android/media/IMediaController2.aidl
rename to apex/media/framework/java/android/media/IMediaController2.aidl
diff --git a/apex/media/java/android/media/IMediaSession2.aidl b/apex/media/framework/java/android/media/IMediaSession2.aidl
similarity index 100%
rename from apex/media/java/android/media/IMediaSession2.aidl
rename to apex/media/framework/java/android/media/IMediaSession2.aidl
diff --git a/apex/media/java/android/media/IMediaSession2Service.aidl b/apex/media/framework/java/android/media/IMediaSession2Service.aidl
similarity index 100%
rename from apex/media/java/android/media/IMediaSession2Service.aidl
rename to apex/media/framework/java/android/media/IMediaSession2Service.aidl
diff --git a/apex/media/java/android/media/MediaConstants.java b/apex/media/framework/java/android/media/MediaConstants.java
similarity index 100%
rename from apex/media/java/android/media/MediaConstants.java
rename to apex/media/framework/java/android/media/MediaConstants.java
diff --git a/apex/media/java/android/media/MediaController2.java b/apex/media/framework/java/android/media/MediaController2.java
similarity index 100%
rename from apex/media/java/android/media/MediaController2.java
rename to apex/media/framework/java/android/media/MediaController2.java
diff --git a/apex/media/java/android/media/MediaParser.java b/apex/media/framework/java/android/media/MediaParser.java
similarity index 100%
rename from apex/media/java/android/media/MediaParser.java
rename to apex/media/framework/java/android/media/MediaParser.java
diff --git a/apex/media/java/android/media/MediaSession2.java b/apex/media/framework/java/android/media/MediaSession2.java
similarity index 100%
rename from apex/media/java/android/media/MediaSession2.java
rename to apex/media/framework/java/android/media/MediaSession2.java
diff --git a/apex/media/java/android/media/MediaSession2Service.java b/apex/media/framework/java/android/media/MediaSession2Service.java
similarity index 100%
rename from apex/media/java/android/media/MediaSession2Service.java
rename to apex/media/framework/java/android/media/MediaSession2Service.java
diff --git a/apex/media/java/android/media/ProxyDataSourceCallback.java b/apex/media/framework/java/android/media/ProxyDataSourceCallback.java
similarity index 100%
rename from apex/media/java/android/media/ProxyDataSourceCallback.java
rename to apex/media/framework/java/android/media/ProxyDataSourceCallback.java
diff --git a/apex/media/java/android/media/RoutingDelegate.java b/apex/media/framework/java/android/media/RoutingDelegate.java
similarity index 100%
rename from apex/media/java/android/media/RoutingDelegate.java
rename to apex/media/framework/java/android/media/RoutingDelegate.java
diff --git a/apex/media/java/android/media/Session2Command.aidl b/apex/media/framework/java/android/media/Session2Command.aidl
similarity index 100%
rename from apex/media/java/android/media/Session2Command.aidl
rename to apex/media/framework/java/android/media/Session2Command.aidl
diff --git a/apex/media/java/android/media/Session2Command.java b/apex/media/framework/java/android/media/Session2Command.java
similarity index 100%
rename from apex/media/java/android/media/Session2Command.java
rename to apex/media/framework/java/android/media/Session2Command.java
diff --git a/apex/media/java/android/media/Session2CommandGroup.java b/apex/media/framework/java/android/media/Session2CommandGroup.java
similarity index 100%
rename from apex/media/java/android/media/Session2CommandGroup.java
rename to apex/media/framework/java/android/media/Session2CommandGroup.java
diff --git a/apex/media/java/android/media/Session2Link.java b/apex/media/framework/java/android/media/Session2Link.java
similarity index 100%
rename from apex/media/java/android/media/Session2Link.java
rename to apex/media/framework/java/android/media/Session2Link.java
diff --git a/apex/media/java/android/media/Session2Token.aidl b/apex/media/framework/java/android/media/Session2Token.aidl
similarity index 100%
rename from apex/media/java/android/media/Session2Token.aidl
rename to apex/media/framework/java/android/media/Session2Token.aidl
diff --git a/apex/media/java/android/media/Session2Token.java b/apex/media/framework/java/android/media/Session2Token.java
similarity index 100%
rename from apex/media/java/android/media/Session2Token.java
rename to apex/media/framework/java/android/media/Session2Token.java
diff --git a/apex/statsd/aidl/Android.bp b/apex/statsd/aidl/Android.bp
index aed6ad9..f8325d4 100644
--- a/apex/statsd/aidl/Android.bp
+++ b/apex/statsd/aidl/Android.bp
@@ -18,6 +18,7 @@
 filegroup {
     name: "statsd_aidl",
     srcs: [
+        "android/os/IPendingIntentRef.aidl",
         "android/os/IPullAtomCallback.aidl",
         "android/os/IPullAtomResultReceiver.aidl",
         "android/os/IStatsCompanionService.aidl",
diff --git a/apex/statsd/aidl/android/os/IPendingIntentRef.aidl b/apex/statsd/aidl/android/os/IPendingIntentRef.aidl
new file mode 100644
index 0000000..6b9e467
--- /dev/null
+++ b/apex/statsd/aidl/android/os/IPendingIntentRef.aidl
@@ -0,0 +1,46 @@
+/*
+ * 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.os;
+
+import android.os.StatsDimensionsValue;
+
+/**
+  * Binder interface to hold a PendingIntent for StatsCompanionService.
+  * {@hide}
+  */
+interface IPendingIntentRef {
+
+    /**
+     * Sends a broadcast to the specified PendingIntent that it should getData now.
+     * This should be only called from StatsCompanionService.
+     */
+     oneway void sendDataBroadcast(long lastReportTimeNs);
+
+    /**
+     * Send a broadcast to the specified PendingIntent notifying it that the list of active configs
+     * has changed. This should be only called from StatsCompanionService.
+     */
+     oneway void sendActiveConfigsChangedBroadcast(in long[] configIds);
+
+     /**
+      * Send a broadcast to the specified PendingIntent, along with the other information
+      * specified. This should only be called from StatsCompanionService.
+      */
+     oneway void sendSubscriberBroadcast(long configUid, long configId, long subscriptionId,
+                                         long subscriptionRuleId, in String[] cookies,
+                                         in StatsDimensionsValue dimensionsValue);
+}
\ No newline at end of file
diff --git a/apex/statsd/aidl/android/os/IStatsCompanionService.aidl b/apex/statsd/aidl/android/os/IStatsCompanionService.aidl
index 5a6118e..21b7767 100644
--- a/apex/statsd/aidl/android/os/IStatsCompanionService.aidl
+++ b/apex/statsd/aidl/android/os/IStatsCompanionService.aidl
@@ -17,7 +17,6 @@
 package android.os;
 
 import android.os.IPullAtomCallback;
-import android.os.StatsDimensionsValue;
 import android.os.StatsLogEventWrapper;
 
 /**
@@ -66,24 +65,6 @@
     /** Pull the specified data. Results will be sent to statsd when complete. */
     StatsLogEventWrapper[] pullData(int pullCode);
 
-    /** Send a broadcast to the specified PendingIntent's as IBinder that it should getData now. */
-    oneway void sendDataBroadcast(in IBinder intentSender, long lastReportTimeNs);
-
-    /**
-     * Send a broadcast to the specified PendingIntent's as IBinder notifying it that the list
-     * of active configs has changed.
-     */
-    oneway void sendActiveConfigsChangedBroadcast(in IBinder intentSender, in long[] configIds);
-
-    /**
-     * Requests StatsCompanionService to send a broadcast using the given intentSender
-     * (which should cast to an IIntentSender), along with the other information specified.
-     */
-    oneway void sendSubscriberBroadcast(in IBinder intentSender, long configUid, long configId,
-                                        long subscriptionId, long subscriptionRuleId,
-                                        in String[] cookies,
-                                        in StatsDimensionsValue dimensionsValue);
-
     /** Tells StatsCompaionService to grab the uid map snapshot and send it to statsd. */
     oneway void triggerUidSnapshot();
 
diff --git a/apex/statsd/aidl/android/os/IStatsManagerService.aidl b/apex/statsd/aidl/android/os/IStatsManagerService.aidl
index 45ba3a2..05583677 100644
--- a/apex/statsd/aidl/android/os/IStatsManagerService.aidl
+++ b/apex/statsd/aidl/android/os/IStatsManagerService.aidl
@@ -30,12 +30,19 @@
      * memory consumed by the metrics for this configuration approach the pre-defined limits. There
      * can be at most one listener per config key.
      *
-     * Requires Manifest.permission.DUMP.
+     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
      */
-    void setDataFetchOperation(long configKey, in PendingIntent pendingIntent,
+    void setDataFetchOperation(long configId, in PendingIntent pendingIntent,
         in String packageName);
 
     /**
+     * Removes the data fetch operation for the specified configuration.
+     *
+     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
+     */
+    void removeDataFetchOperation(long configId, in String packageName);
+
+    /**
      * Registers the given pending intent for this packagename. This intent is invoked when the
      * active status of any of the configs sent by this package changes and will contain a list of
      * config ids that are currently active. It also returns the list of configs that are currently
@@ -46,6 +53,13 @@
     long[] setActiveConfigsChangedOperation(in PendingIntent pendingIntent, in String packageName);
 
     /**
+     * Removes the active configs changed operation for the specified package name.
+     *
+     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
+     */
+    void removeActiveConfigsChangedOperation(in String packageName);
+
+    /**
      * Set the PendingIntent to be used when broadcasting subscriber
      * information to the given subscriberId within the given config.
      *
@@ -58,8 +72,17 @@
      * This function can only be called by the owner (uid) of the config. It must be called each
      * time statsd starts. Later calls overwrite previous calls; only one PendingIntent is stored.
      *
-     * Requires Manifest.permission.DUMP.
+     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
      */
     void setBroadcastSubscriber(long configKey, long subscriberId, in PendingIntent pendingIntent,
                                 in String packageName);
+
+    /**
+     * Undoes setBroadcastSubscriber() for the (configKey, subscriberId) pair.
+     * Any broadcasts associated with subscriberId will henceforth not be sent.
+     * No-op if this (configKey, subscriberId) pair was not associated with an PendingIntent.
+     *
+     * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
+     */
+    void unsetBroadcastSubscriber(long configKey, long subscriberId, in String packageName);
 }
\ No newline at end of file
diff --git a/apex/statsd/aidl/android/os/IStatsd.aidl b/apex/statsd/aidl/android/os/IStatsd.aidl
index cce79fa..9358439 100644
--- a/apex/statsd/aidl/android/os/IStatsd.aidl
+++ b/apex/statsd/aidl/android/os/IStatsd.aidl
@@ -17,6 +17,7 @@
 package android.os;
 
 import android.os.IStatsPullerCallback;
+import android.os.IPendingIntentRef;
 import android.os.IPullAtomCallback;
 import android.os.ParcelFileDescriptor;
 
@@ -114,14 +115,15 @@
      *
      * Requires Manifest.permission.DUMP.
      */
-    void setDataFetchOperation(long configKey, in IBinder intentSender, in String packageName);
+    void setDataFetchOperation(long configId, in IPendingIntentRef pendingIntentRef,
+                               int callingUid);
 
     /**
      * Removes the data fetch operation for the specified configuration.
      *
      * Requires Manifest.permission.DUMP.
      */
-    void removeDataFetchOperation(long configKey, in String packageName);
+    void removeDataFetchOperation(long configId, int callingUid);
 
     /**
      * Registers the given pending intent for this packagename. This intent is invoked when the
@@ -131,14 +133,14 @@
      *
      * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
      */
-    long[] setActiveConfigsChangedOperation(in IBinder intentSender, in String packageName);
+    long[] setActiveConfigsChangedOperation(in IPendingIntentRef pendingIntentRef, int callingUid);
 
     /**
      * Removes the active configs changed operation for the specified package name.
      *
      * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS.
      */
-    void removeActiveConfigsChangedOperation(in String packageName);
+    void removeActiveConfigsChangedOperation(int callingUid);
 
     /**
      * Removes the configuration with the matching config key. No-op if this config key does not
@@ -149,34 +151,31 @@
     void removeConfiguration(in long configKey, in String packageName);
 
     /**
-     * Set the IIntentSender (i.e. PendingIntent) to be used when broadcasting subscriber
+     * Set the PendingIntentRef to be used when broadcasting subscriber
      * information to the given subscriberId within the given config.
      *
-     * Suppose that the calling uid has added a config with key configKey, and that in this config
+     * Suppose that the calling uid has added a config with key configId, and that in this config
      * it is specified that when a particular anomaly is detected, a broadcast should be sent to
-     * a BroadcastSubscriber with id subscriberId. This function links the given intentSender with
-     * that subscriberId (for that config), so that this intentSender is used to send the broadcast
+     * a BroadcastSubscriber with id subscriberId. This function links the given pendingIntent with
+     * that subscriberId (for that config), so that this pendingIntent is used to send the broadcast
      * when the anomaly is detected.
      *
      * This function can only be called by the owner (uid) of the config. It must be called each
-     * time statsd starts. Later calls overwrite previous calls; only one intentSender is stored.
-     *
-     * intentSender must be convertible into an IntentSender using IntentSender(IBinder)
-     * and cannot be null.
+     * time statsd starts. Later calls overwrite previous calls; only one pendingIntent is stored.
      *
      * Requires Manifest.permission.DUMP.
      */
-    void setBroadcastSubscriber(long configKey, long subscriberId, in IBinder intentSender,
-                                in String packageName);
+    void setBroadcastSubscriber(long configId, long subscriberId, in IPendingIntentRef pir,
+                                int callingUid);
 
     /**
-     * Undoes setBroadcastSubscriber() for the (configKey, subscriberId) pair.
+     * Undoes setBroadcastSubscriber() for the (configId, subscriberId) pair.
      * Any broadcasts associated with subscriberId will henceforth not be sent.
-     * No-op if this (configKey, subsriberId) pair was not associated with an IntentSender.
+     * No-op if this (configKey, subscriberId) pair was not associated with an PendingIntentRef.
      *
      * Requires Manifest.permission.DUMP.
      */
-    void unsetBroadcastSubscriber(long configKey, long subscriberId, in String packageName);
+    void unsetBroadcastSubscriber(long configId, long subscriberId, int callingUid);
 
     /**
      * Apps can send an atom via this application breadcrumb with the specified label and state for
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanion.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanion.java
index 71b52e2..4383b50 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanion.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanion.java
@@ -16,11 +16,21 @@
 
 package com.android.server.stats;
 
+import android.app.PendingIntent;
+import android.app.StatsManager;
 import android.content.Context;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IPendingIntentRef;
+import android.os.Process;
+import android.os.StatsDimensionsValue;
 import android.util.Slog;
 
 import com.android.server.SystemService;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+
 /**
  * @hide
  */
@@ -28,6 +38,13 @@
     private static final String TAG = "StatsCompanion";
     private static final boolean DEBUG = false;
 
+    static void enforceStatsCompanionPermission(Context context) {
+        if (Binder.getCallingPid() == Process.myPid()) {
+            return;
+        }
+        context.enforceCallingPermission(android.Manifest.permission.STATSCOMPANION, null);
+    }
+
     /**
      * Lifecycle class for both {@link StatsCompanionService} and {@link StatsManagerService}.
      */
@@ -63,7 +80,97 @@
             super.onBootPhase(phase);
             if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
                 mStatsCompanionService.systemReady();
-                mStatsManagerService.systemReady();
+            }
+        }
+    }
+
+    /**
+     * Wrapper for {@link PendingIntent}. Allows Statsd to send PendingIntents.
+     */
+    public static class PendingIntentRef extends IPendingIntentRef.Stub {
+
+        private static final String TAG = "PendingIntentRef";
+
+        /**
+         * The last report time is provided with each intent registered to
+         * StatsManager#setFetchReportsOperation. This allows easy de-duping in the receiver if
+         * statsd is requesting the client to retrieve the same statsd data. The last report time
+         * corresponds to the last_report_elapsed_nanos that will provided in the current
+         * ConfigMetricsReport, and this timestamp also corresponds to the
+         * current_report_elapsed_nanos of the most recently obtained ConfigMetricsReport.
+         */
+        private static final String EXTRA_LAST_REPORT_TIME = "android.app.extra.LAST_REPORT_TIME";
+        private static final int CODE_DATA_BROADCAST = 1;
+        private static final int CODE_ACTIVE_CONFIGS_BROADCAST = 1;
+        private static final int CODE_SUBSCRIBER_BROADCAST = 1;
+
+        private final PendingIntent mPendingIntent;
+        private final Context mContext;
+
+        public PendingIntentRef(PendingIntent pendingIntent, Context context) {
+            mPendingIntent = pendingIntent;
+            mContext = context;
+        }
+
+        @Override
+        public void sendDataBroadcast(long lastReportTimeNs) {
+            enforceStatsCompanionPermission(mContext);
+            Intent intent = new Intent();
+            intent.putExtra(EXTRA_LAST_REPORT_TIME, lastReportTimeNs);
+            try {
+                mPendingIntent.send(mContext, CODE_DATA_BROADCAST, intent, null, null);
+            } catch (PendingIntent.CanceledException e) {
+                Slog.w(TAG, "Unable to send PendingIntent");
+            }
+        }
+
+        @Override
+        public void sendActiveConfigsChangedBroadcast(long[] configIds) {
+            enforceStatsCompanionPermission(mContext);
+            Intent intent = new Intent();
+            intent.putExtra(StatsManager.EXTRA_STATS_ACTIVE_CONFIG_KEYS, configIds);
+            try {
+                mPendingIntent.send(mContext, CODE_ACTIVE_CONFIGS_BROADCAST, intent, null, null);
+                if (DEBUG) {
+                    Slog.d(TAG, "Sent broadcast with config ids " + Arrays.toString(configIds));
+                }
+            } catch (PendingIntent.CanceledException e) {
+                Slog.w(TAG, "Unable to send active configs changed broadcast using PendingIntent");
+            }
+        }
+
+        @Override
+        public void sendSubscriberBroadcast(long configUid, long configId, long subscriptionId,
+                long subscriptionRuleId, String[] cookies, StatsDimensionsValue dimensionsValue) {
+            enforceStatsCompanionPermission(mContext);
+            Intent intent =
+                    new Intent()
+                            .putExtra(StatsManager.EXTRA_STATS_CONFIG_UID, configUid)
+                            .putExtra(StatsManager.EXTRA_STATS_CONFIG_KEY, configId)
+                            .putExtra(StatsManager.EXTRA_STATS_SUBSCRIPTION_ID, subscriptionId)
+                            .putExtra(StatsManager.EXTRA_STATS_SUBSCRIPTION_RULE_ID,
+                                    subscriptionRuleId)
+                            .putExtra(StatsManager.EXTRA_STATS_DIMENSIONS_VALUE, dimensionsValue);
+
+            ArrayList<String> cookieList = new ArrayList<>(cookies.length);
+            cookieList.addAll(Arrays.asList(cookies));
+            intent.putStringArrayListExtra(
+                    StatsManager.EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES, cookieList);
+
+            if (DEBUG) {
+                Slog.d(TAG,
+                        String.format(
+                                "Statsd sendSubscriberBroadcast with params {%d %d %d %d %s %s}",
+                                configUid, configId, subscriptionId, subscriptionRuleId,
+                                Arrays.toString(cookies),
+                                dimensionsValue));
+            }
+            try {
+                mPendingIntent.send(mContext, CODE_SUBSCRIBER_BROADCAST, intent, null, null);
+            } catch (PendingIntent.CanceledException e) {
+                Slog.w(TAG,
+                        "Unable to send using PendingIntent from uid " + configUid
+                                + "; presumably it had been cancelled.");
             }
         }
     }
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 e4f7300..d57afee 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
@@ -50,7 +50,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.IntentSender;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -85,11 +84,9 @@
 import android.os.Looper;
 import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
-import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.StatFs;
-import android.os.StatsDimensionsValue;
 import android.os.StatsLogEventWrapper;
 import android.os.SynchronousResultReceiver;
 import android.os.SystemClock;
@@ -203,18 +200,6 @@
     private static final int PACKAGE_NAME_FIELD_ID = 4;
     private static final int INSTALLER_FIELD_ID = 5;
 
-    public static final int CODE_DATA_BROADCAST = 1;
-    public static final int CODE_SUBSCRIBER_BROADCAST = 1;
-    public static final int CODE_ACTIVE_CONFIGS_BROADCAST = 1;
-    /**
-     * The last report time is provided with each intent registered to
-     * StatsManager#setFetchReportsOperation. This allows easy de-duping in the receiver if
-     * statsd is requesting the client to retrieve the same statsd data. The last report time
-     * corresponds to the last_report_elapsed_nanos that will provided in the current
-     * ConfigMetricsReport, and this timestamp also corresponds to the
-     * current_report_elapsed_nanos of the most recently obtained ConfigMetricsReport.
-     */
-    public static final String EXTRA_LAST_REPORT_TIME = "android.app.extra.LAST_REPORT_TIME";
     public static final int DEATH_THRESHOLD = 10;
     /**
      * Which native processes to snapshot memory for.
@@ -454,72 +439,6 @@
                 KernelCpuThreadReaderSettingsObserver.getSettingsModifiedReader(mContext);
     }
 
-    @Override
-    public void sendDataBroadcast(IBinder intentSenderBinder, long lastReportTimeNs) {
-        enforceCallingPermission();
-        IntentSender intentSender = new IntentSender(intentSenderBinder);
-        Intent intent = new Intent();
-        intent.putExtra(EXTRA_LAST_REPORT_TIME, lastReportTimeNs);
-        try {
-            intentSender.sendIntent(mContext, CODE_DATA_BROADCAST, intent, null, null);
-        } catch (IntentSender.SendIntentException e) {
-            Slog.w(TAG, "Unable to send using IntentSender");
-        }
-    }
-
-    @Override
-    public void sendActiveConfigsChangedBroadcast(IBinder intentSenderBinder, long[] configIds) {
-        enforceCallingPermission();
-        IntentSender intentSender = new IntentSender(intentSenderBinder);
-        Intent intent = new Intent();
-        intent.putExtra(StatsManager.EXTRA_STATS_ACTIVE_CONFIG_KEYS, configIds);
-        try {
-            intentSender.sendIntent(mContext, CODE_ACTIVE_CONFIGS_BROADCAST, intent, null, null);
-            if (DEBUG) {
-                Slog.d(TAG, "Sent broadcast with config ids " + Arrays.toString(configIds));
-            }
-        } catch (IntentSender.SendIntentException e) {
-            Slog.w(TAG, "Unable to send active configs changed broadcast using IntentSender");
-        }
-    }
-
-    @Override
-    public void sendSubscriberBroadcast(IBinder intentSenderBinder, long configUid, long configKey,
-            long subscriptionId, long subscriptionRuleId, String[] cookies,
-            StatsDimensionsValue dimensionsValue) {
-        enforceCallingPermission();
-        IntentSender intentSender = new IntentSender(intentSenderBinder);
-        Intent intent =
-                new Intent()
-                        .putExtra(StatsManager.EXTRA_STATS_CONFIG_UID, configUid)
-                        .putExtra(StatsManager.EXTRA_STATS_CONFIG_KEY, configKey)
-                        .putExtra(StatsManager.EXTRA_STATS_SUBSCRIPTION_ID, subscriptionId)
-                        .putExtra(StatsManager.EXTRA_STATS_SUBSCRIPTION_RULE_ID, subscriptionRuleId)
-                        .putExtra(StatsManager.EXTRA_STATS_DIMENSIONS_VALUE, dimensionsValue);
-
-        ArrayList<String> cookieList = new ArrayList<>(cookies.length);
-        for (String cookie : cookies) {
-            cookieList.add(cookie);
-        }
-        intent.putStringArrayListExtra(
-                StatsManager.EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES, cookieList);
-
-        if (DEBUG) {
-            Slog.d(TAG,
-                    String.format("Statsd sendSubscriberBroadcast with params {%d %d %d %d %s %s}",
-                            configUid, configKey, subscriptionId, subscriptionRuleId,
-                            Arrays.toString(cookies),
-                            dimensionsValue));
-        }
-        try {
-            intentSender.sendIntent(mContext, CODE_SUBSCRIBER_BROADCAST, intent, null, null);
-        } catch (IntentSender.SendIntentException e) {
-            Slog.w(TAG,
-                    "Unable to send using IntentSender from uid " + configUid
-                            + "; presumably it had been cancelled.");
-        }
-    }
-
     private final static int[] toIntArray(List<Integer> list) {
         int[] ret = new int[list.size()];
         for (int i = 0; i < ret.length; i++) {
@@ -770,7 +689,7 @@
 
     @Override // Binder call
     public void setAnomalyAlarm(long timestampMs) {
-        enforceCallingPermission();
+        StatsCompanion.enforceStatsCompanionPermission(mContext);
         if (DEBUG) Slog.d(TAG, "Setting anomaly alarm for " + timestampMs);
         final long callingToken = Binder.clearCallingIdentity();
         try {
@@ -786,7 +705,7 @@
 
     @Override // Binder call
     public void cancelAnomalyAlarm() {
-        enforceCallingPermission();
+        StatsCompanion.enforceStatsCompanionPermission(mContext);
         if (DEBUG) Slog.d(TAG, "Cancelling anomaly alarm");
         final long callingToken = Binder.clearCallingIdentity();
         try {
@@ -798,7 +717,7 @@
 
     @Override // Binder call
     public void setAlarmForSubscriberTriggering(long timestampMs) {
-        enforceCallingPermission();
+        StatsCompanion.enforceStatsCompanionPermission(mContext);
         if (DEBUG) {
             Slog.d(TAG,
                     "Setting periodic alarm in about " + (timestampMs
@@ -817,7 +736,7 @@
 
     @Override // Binder call
     public void cancelAlarmForSubscriberTriggering() {
-        enforceCallingPermission();
+        StatsCompanion.enforceStatsCompanionPermission(mContext);
         if (DEBUG) {
             Slog.d(TAG, "Cancelling periodic alarm");
         }
@@ -831,7 +750,7 @@
 
     @Override // Binder call
     public void setPullingAlarm(long nextPullTimeMs) {
-        enforceCallingPermission();
+        StatsCompanion.enforceStatsCompanionPermission(mContext);
         if (DEBUG) {
             Slog.d(TAG, "Setting pulling alarm in about "
                     + (nextPullTimeMs - SystemClock.elapsedRealtime()));
@@ -849,7 +768,7 @@
 
     @Override // Binder call
     public void cancelPullingAlarm() {
-        enforceCallingPermission();
+        StatsCompanion.enforceStatsCompanionPermission(mContext);
         if (DEBUG) {
             Slog.d(TAG, "Cancelling pulling alarm");
         }
@@ -2455,7 +2374,7 @@
      */
     @Override // Binder call
     public StatsLogEventWrapper[] pullData(int tagId) {
-        enforceCallingPermission();
+        StatsCompanion.enforceStatsCompanionPermission(mContext);
         if (DEBUG) {
             Slog.d(TAG, "Pulling " + tagId);
         }
@@ -2690,12 +2609,11 @@
 
     @Override // Binder call
     public void statsdReady() {
-        enforceCallingPermission();
+        StatsCompanion.enforceStatsCompanionPermission(mContext);
         if (DEBUG) {
             Slog.d(TAG, "learned that statsdReady");
         }
         sayHiToStatsd(); // tell statsd that we're ready too and link to it
-        mStatsManagerService.systemReady();
         mContext.sendBroadcastAsUser(new Intent(StatsManager.ACTION_STATSD_STARTED)
                         .addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND),
                 UserHandle.SYSTEM, android.Manifest.permission.DUMP);
@@ -2703,7 +2621,7 @@
 
     @Override
     public void triggerUidSnapshot() {
-        enforceCallingPermission();
+        StatsCompanion.enforceStatsCompanionPermission(mContext);
         synchronized (sStatsdLock) {
             final long token = Binder.clearCallingIdentity();
             try {
@@ -2716,13 +2634,6 @@
         }
     }
 
-    private void enforceCallingPermission() {
-        if (Binder.getCallingPid() == Process.myPid()) {
-            return;
-        }
-        mContext.enforceCallingPermission(android.Manifest.permission.STATSCOMPANION, null);
-    }
-
     @Override
     public void registerPullAtomCallback(int atomTag, long coolDownNs, long timeoutNs,
             int[] additiveFields, IPullAtomCallback pullerCallback) {
@@ -2817,6 +2728,7 @@
                                 + "alive.");
                 return;
             }
+            mStatsManagerService.statsdReady(sStatsd);
             if (DEBUG) Slog.d(TAG, "Saying hi to statsd");
             try {
                 sStatsd.statsCompanionReady();
@@ -2928,6 +2840,7 @@
         if (looperStats != null) {
             looperStats.reset();
         }
+        mStatsManagerService.statsdNotReady();
     }
 
     @Override
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java b/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java
index 24b7978..1d03e3b 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java
@@ -16,18 +16,28 @@
 
 package com.android.server.stats;
 
+import static com.android.server.stats.StatsCompanion.PendingIntentRef;
+
+import android.Manifest;
+import android.app.AppOpsManager;
 import android.app.PendingIntent;
 import android.content.Context;
-import android.os.IBinder;
+import android.os.Binder;
 import android.os.IStatsManagerService;
 import android.os.IStatsd;
+import android.os.Process;
 import android.os.RemoteException;
-import android.os.ServiceManager;
+import android.util.ArrayMap;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
 
+import java.util.Map;
+import java.util.Objects;
+
 /**
+ * Service for {@link android.app.StatsManager}.
+ *
  * @hide
  */
 public class StatsManagerService extends IStatsManagerService.Stub {
@@ -35,41 +45,203 @@
     private static final String TAG = "StatsManagerService";
     private static final boolean DEBUG = false;
 
-    @GuardedBy("sStatsdLock")
-    private static IStatsd sStatsd;
-    private static final Object sStatsdLock = new Object();
+    private static final int STATSD_TIMEOUT_MILLIS = 5000;
+
+    private static final String USAGE_STATS_PERMISSION_OPS = "android:get_usage_stats";
+
+    @GuardedBy("mLock")
+    private IStatsd mStatsd;
+    private final Object mLock = new Object();
 
     private StatsCompanionService mStatsCompanionService;
+    private Context mContext;
+
+    @GuardedBy("mLock")
+    private ArrayMap<ConfigKey, PendingIntentRef> mDataFetchPirMap = new ArrayMap<>();
+    @GuardedBy("mLock")
+    private ArrayMap<Integer, PendingIntentRef> mActiveConfigsPirMap =
+            new ArrayMap<>();
+    @GuardedBy("mLock")
+    private ArrayMap<ConfigKey, ArrayMap<Long, PendingIntentRef>> mBroadcastSubscriberPirMap =
+            new ArrayMap<>();
 
     public StatsManagerService(Context context) {
         super();
+        mContext = context;
+    }
+
+    private static class ConfigKey {
+        private int mUid;
+        private long mConfigId;
+
+        ConfigKey(int uid, long configId) {
+            mUid = uid;
+            mConfigId = configId;
+        }
+
+        public int getUid() {
+            return mUid;
+        }
+
+        public long getConfigId() {
+            return mConfigId;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mUid, mConfigId);
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof ConfigKey) {
+                ConfigKey other = (ConfigKey) obj;
+                return this.mUid == other.getUid() && this.mConfigId == other.getConfigId();
+            }
+            return false;
+        }
     }
 
     @Override
-    public void setDataFetchOperation(long configKey, PendingIntent pendingIntent,
+    public void setDataFetchOperation(long configId, PendingIntent pendingIntent,
             String packageName) {
-        // no-op
-        if (DEBUG) {
-            Slog.d(TAG, "setDataFetchOperation");
+        enforceDumpAndUsageStatsPermission(packageName);
+        int callingUid = Binder.getCallingUid();
+        final long token = Binder.clearCallingIdentity();
+        PendingIntentRef pir = new PendingIntentRef(pendingIntent, mContext);
+        ConfigKey key = new ConfigKey(callingUid, configId);
+        // We add the PIR to a map so we can reregister if statsd is unavailable.
+        synchronized (mLock) {
+            mDataFetchPirMap.put(key, pir);
+        }
+        try {
+            IStatsd statsd = getStatsdNonblocking();
+            if (statsd != null) {
+                statsd.setDataFetchOperation(configId, pir, callingUid);
+            }
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Failed to setDataFetchOperation with statsd");
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    @Override
+    public void removeDataFetchOperation(long configId, String packageName) {
+        enforceDumpAndUsageStatsPermission(packageName);
+        int callingUid = Binder.getCallingUid();
+        final long token = Binder.clearCallingIdentity();
+        ConfigKey key = new ConfigKey(callingUid, configId);
+        synchronized (mLock) {
+            mDataFetchPirMap.remove(key);
+        }
+        try {
+            IStatsd statsd = getStatsdNonblocking();
+            if (statsd != null) {
+                statsd.removeDataFetchOperation(configId, callingUid);
+            }
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Failed to removeDataFetchOperation with statsd");
+        } finally {
+            Binder.restoreCallingIdentity(token);
         }
     }
 
     @Override
     public long[] setActiveConfigsChangedOperation(PendingIntent pendingIntent,
             String packageName) {
-        // no-op
-        if (DEBUG) {
-            Slog.d(TAG, "setActiveConfigsChangedOperation");
+        enforceDumpAndUsageStatsPermission(packageName);
+        int callingUid = Binder.getCallingUid();
+        final long token = Binder.clearCallingIdentity();
+        PendingIntentRef pir = new PendingIntentRef(pendingIntent, mContext);
+        // We add the PIR to a map so we can reregister if statsd is unavailable.
+        synchronized (mLock) {
+            mActiveConfigsPirMap.put(callingUid, pir);
         }
-        return new long[]{};
+        try {
+            IStatsd statsd = getStatsdNonblocking();
+            if (statsd != null) {
+                return statsd.setActiveConfigsChangedOperation(pir, callingUid);
+            }
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Failed to setActiveConfigsChangedOperation with statsd");
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+        return new long[] {};
     }
 
     @Override
-    public void setBroadcastSubscriber(long configKey, long subscriberId,
+    public void removeActiveConfigsChangedOperation(String packageName) {
+        enforceDumpAndUsageStatsPermission(packageName);
+        int callingUid = Binder.getCallingUid();
+        final long token = Binder.clearCallingIdentity();
+        synchronized (mLock) {
+            mActiveConfigsPirMap.remove(callingUid);
+        }
+        try {
+            IStatsd statsd = getStatsdNonblocking();
+            if (statsd != null) {
+                statsd.removeActiveConfigsChangedOperation(callingUid);
+            }
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Failed to removeActiveConfigsChangedOperation with statsd");
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    @Override
+    public void setBroadcastSubscriber(long configId, long subscriberId,
             PendingIntent pendingIntent, String packageName) {
-        //no-op
-        if (DEBUG) {
-            Slog.d(TAG, "setBroadcastSubscriber");
+        enforceDumpAndUsageStatsPermission(packageName);
+        int callingUid = Binder.getCallingUid();
+        final long token = Binder.clearCallingIdentity();
+        PendingIntentRef pir = new PendingIntentRef(pendingIntent, mContext);
+        ConfigKey key = new ConfigKey(callingUid, configId);
+        // We add the PIR to a map so we can reregister if statsd is unavailable.
+        synchronized (mLock) {
+            ArrayMap<Long, PendingIntentRef> innerMap = mBroadcastSubscriberPirMap
+                    .getOrDefault(key, new ArrayMap<>());
+            innerMap.put(subscriberId, pir);
+            mBroadcastSubscriberPirMap.put(key, innerMap);
+        }
+        try {
+            IStatsd statsd = getStatsdNonblocking();
+            if (statsd != null) {
+                statsd.setBroadcastSubscriber(
+                        configId, subscriberId, pir, callingUid);
+            }
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Failed to setBroadcastSubscriber with statsd");
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    @Override
+    public void unsetBroadcastSubscriber(long configId, long subscriberId, String packageName) {
+        enforceDumpAndUsageStatsPermission(packageName);
+        int callingUid = Binder.getCallingUid();
+        final long token = Binder.clearCallingIdentity();
+        ConfigKey key = new ConfigKey(callingUid, configId);
+        synchronized (mLock) {
+            ArrayMap<Long, PendingIntentRef> innerMap = mBroadcastSubscriberPirMap
+                    .getOrDefault(key, new ArrayMap<>());
+            innerMap.remove(subscriberId);
+            if (innerMap.isEmpty()) {
+                mBroadcastSubscriberPirMap.remove(key);
+            }
+        }
+        try {
+            IStatsd statsd = getStatsdNonblocking();
+            if (statsd != null) {
+                statsd.unsetBroadcastSubscriber(configId, subscriberId, callingUid);
+            }
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Failed to unsetBroadcastSubscriber with statsd");
+        } finally {
+            Binder.restoreCallingIdentity(token);
         }
     }
 
@@ -77,37 +249,130 @@
         mStatsCompanionService = statsCompanionService;
     }
 
-    void systemReady() {
-        if (DEBUG) {
-            Slog.d(TAG, "statsdReady");
+    private void enforceDumpAndUsageStatsPermission(String packageName) {
+        int callingUid = Binder.getCallingUid();
+        int callingPid = Binder.getCallingPid();
+
+        if (callingPid == Process.myPid()) {
+            return;
         }
-        setupStatsManagerService();
+        mContext.enforceCallingPermission(Manifest.permission.DUMP, null);
+        mContext.enforceCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS, null);
+
+        AppOpsManager appOpsManager = (AppOpsManager) mContext
+                .getSystemService(Context.APP_OPS_SERVICE);
+        switch (appOpsManager.noteOp(USAGE_STATS_PERMISSION_OPS,
+                Binder.getCallingUid(), packageName, null, null)) {
+            case AppOpsManager.MODE_ALLOWED:
+            case AppOpsManager.MODE_DEFAULT:
+                break;
+            default:
+                throw new SecurityException(
+                        String.format("UID %d / PID %d lacks app-op %s",
+                                callingUid, callingPid, USAGE_STATS_PERMISSION_OPS)
+                );
+        }
     }
 
-    private void setupStatsManagerService() {
-        synchronized (sStatsdLock) {
-            if (sStatsd != null) {
-                if (DEBUG) {
-                    Slog.e(TAG, "Trying to fetch statsd, but it was already fetched",
-                            new IllegalStateException(
-                                    "sStatsd is not null when being fetched"));
+    /**
+     * Clients should call this if blocking until statsd to be ready is desired
+     *
+     * @return IStatsd object if statsd becomes ready within the timeout, null otherwise.
+     */
+    private IStatsd waitForStatsd() {
+        synchronized (mLock) {
+            if (mStatsd == null) {
+                try {
+                    mLock.wait(STATSD_TIMEOUT_MILLIS);
+                } catch (InterruptedException e) {
+                    Slog.e(TAG, "wait for statsd interrupted");
                 }
-                return;
             }
-            sStatsd = IStatsd.Stub.asInterface(ServiceManager.getService("stats"));
-            if (sStatsd == null) {
-                if (DEBUG) {
-                    Slog.d(TAG, "Failed to get stats service.");
-                }
-                return;
+            return mStatsd;
+        }
+    }
+
+    /**
+     * Clients should call this to receive a reference to statsd.
+     *
+     * @return IStatsd object if statsd is ready, null otherwise.
+     */
+    private IStatsd getStatsdNonblocking() {
+        synchronized (mLock) {
+            return mStatsd;
+        }
+    }
+
+    /**
+     * Called from {@link StatsCompanionService}.
+     *
+     * Tells StatsManagerService that Statsd is ready and updates
+     * Statsd with the contents of our local cache.
+     */
+    void statsdReady(IStatsd statsd) {
+        synchronized (mLock) {
+            mStatsd = statsd;
+            mLock.notify();
+        }
+        sayHiToStatsd(statsd);
+    }
+
+    /**
+     * Called from {@link StatsCompanionService}.
+     *
+     * Tells StatsManagerService that Statsd is no longer ready
+     * and we should no longer make binder calls with statsd.
+     */
+    void statsdNotReady() {
+        synchronized (mLock) {
+            mStatsd = null;
+        }
+    }
+
+    private void sayHiToStatsd(IStatsd statsd) {
+        if (statsd == null) {
+            return;
+        }
+        // Since we do not want to make an IPC with the a lock held, we first create local deep
+        // copies of the data with the lock held before iterating through the maps.
+        ArrayMap<ConfigKey, PendingIntentRef> dataFetchCopy;
+        ArrayMap<Integer, PendingIntentRef> activeConfigsChangedCopy;
+        ArrayMap<ConfigKey, ArrayMap<Long, PendingIntentRef>> broadcastSubscriberCopy;
+        synchronized (mLock) {
+            dataFetchCopy = new ArrayMap<>(mDataFetchPirMap);
+            activeConfigsChangedCopy = new ArrayMap<>(mActiveConfigsPirMap);
+            broadcastSubscriberCopy = new ArrayMap<>();
+            for (Map.Entry<ConfigKey, ArrayMap<Long, PendingIntentRef>> entry
+                    : mBroadcastSubscriberPirMap.entrySet()) {
+                broadcastSubscriberCopy.put(entry.getKey(), new ArrayMap<>(entry.getValue()));
             }
-            // Assume statsd is ready since this is called form statscompanion, link to statsd.
+        }
+        for (Map.Entry<ConfigKey, PendingIntentRef> entry : dataFetchCopy.entrySet()) {
+            ConfigKey key = entry.getKey();
             try {
-                sStatsd.asBinder().linkToDeath((IBinder.DeathRecipient) () -> {
-                    sStatsd = null;
-                }, 0);
+                statsd.setDataFetchOperation(key.getConfigId(), entry.getValue(), key.getUid());
             } catch (RemoteException e) {
-                Slog.e(TAG, "linkToDeath(StatsdDeathRecipient) failed", e);
+                Slog.e(TAG, "Failed to setDataFetchOperation from pirMap");
+            }
+        }
+        for (Map.Entry<Integer, PendingIntentRef> entry
+                : activeConfigsChangedCopy.entrySet()) {
+            try {
+                statsd.setActiveConfigsChangedOperation(entry.getValue(), entry.getKey());
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to setActiveConfigsChangedOperation from pirMap");
+            }
+        }
+        for (Map.Entry<ConfigKey, ArrayMap<Long, PendingIntentRef>> entry
+                : broadcastSubscriberCopy.entrySet()) {
+            for (Map.Entry<Long, PendingIntentRef> subscriberEntry : entry.getValue().entrySet()) {
+                ConfigKey configKey = entry.getKey();
+                try {
+                    statsd.setBroadcastSubscriber(configKey.getConfigId(), subscriberEntry.getKey(),
+                            subscriberEntry.getValue(), configKey.getUid());
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Failed to setBroadcastSubscriber from pirMap");
+                }
             }
         }
     }
diff --git a/api/current.txt b/api/current.txt
index 33b3b09..ea8397a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -30236,6 +30236,7 @@
 
   @Deprecated public class WifiConfiguration implements android.os.Parcelable {
     ctor @Deprecated public WifiConfiguration();
+    ctor @Deprecated public WifiConfiguration(@NonNull android.net.wifi.WifiConfiguration);
     method public int describeContents();
     method @Deprecated public android.net.ProxyInfo getHttpProxy();
     method @Deprecated @NonNull public String getKey();
@@ -45648,6 +45649,7 @@
     method public int getLevel();
     method @Deprecated public boolean isGsm();
     method public void writeToParcel(android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SignalStrength> CREATOR;
     field public static final int INVALID = 2147483647; // 0x7fffffff
   }
 
@@ -45656,7 +45658,7 @@
     method @Nullable public String createAppSpecificSmsTokenWithPackageInfo(@Nullable String, @NonNull android.app.PendingIntent);
     method public java.util.ArrayList<java.lang.String> divideMessage(String);
     method public void downloadMultimediaMessage(android.content.Context, String, android.net.Uri, android.os.Bundle, android.app.PendingIntent);
-    method public android.os.Bundle getCarrierConfigValues();
+    method @Nullable public android.os.Bundle getCarrierConfigValues();
     method public static android.telephony.SmsManager getDefault();
     method public static int getDefaultSmsSubscriptionId();
     method public static android.telephony.SmsManager getSmsManagerForSubscriptionId(int);
diff --git a/api/system-current.txt b/api/system-current.txt
index f73a1fa..39bf88e 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1268,6 +1268,7 @@
     method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void addRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
     method @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public boolean addRoleHolderFromController(@NonNull String, @NonNull String);
     method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void clearRoleHoldersAsUser(@NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
+    method @Nullable public String getDefaultSmsPackage(int);
     method @NonNull @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public java.util.List<java.lang.String> getHeldRolesFromController(@NonNull String);
     method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public java.util.List<java.lang.String> getRoleHolders(@NonNull String);
     method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public java.util.List<java.lang.String> getRoleHoldersAsUser(@NonNull String, @NonNull android.os.UserHandle);
@@ -9824,6 +9825,10 @@
     field public static final int ROAMING_TYPE_UNKNOWN = 1; // 0x1
   }
 
+  public class SignalStrength implements android.os.Parcelable {
+    ctor public SignalStrength(@NonNull android.telephony.SignalStrength);
+  }
+
   public final class SmsCbCmasInfo implements android.os.Parcelable {
     ctor public SmsCbCmasInfo(int, int, int, int, int, int);
     method public int describeContents();
@@ -10095,6 +10100,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isEmergencyAssistanceEnabled();
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isIdle();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isInEmergencySmsMode();
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isManualNetworkSelectionAllowed();
     method public boolean isModemEnabledForSlot(int);
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isOffhook();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isOpportunisticNetworkEnabled();
@@ -10117,6 +10123,7 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean resetRadioConfig();
     method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void resetSettings();
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAlwaysAllowMmsData(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setCarrierRestrictionRules(@NonNull android.telephony.CarrierRestrictionRules);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataActivationState(int);
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index bb3a094..5ff0f97 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -170,33 +170,32 @@
             mUidMap, mPullerManager, mAnomalyAlarmMonitor, mPeriodicAlarmMonitor,
             getElapsedRealtimeNs(),
             [this](const ConfigKey& key) {
-                sp<IStatsCompanionService> sc = getStatsCompanionService();
-                auto receiver = mConfigManager->GetConfigReceiver(key);
-                if (sc == nullptr) {
-                    VLOG("Could not find StatsCompanionService");
+                sp<IPendingIntentRef> receiver = mConfigManager->GetConfigReceiver(key);
+                if (receiver == nullptr) {
+                    VLOG("Could not find a broadcast receiver for %s",
+                        key.ToString().c_str());
                     return false;
-                } else if (receiver == nullptr) {
-                    VLOG("Statscompanion could not find a broadcast receiver for %s",
-                         key.ToString().c_str());
-                    return false;
-                } else {
-                    sc->sendDataBroadcast(receiver, mProcessor->getLastReportTimeNs(key));
+                } else if (receiver->sendDataBroadcast(
+                           mProcessor->getLastReportTimeNs(key)).isOk()) {
                     return true;
+                } else {
+                    VLOG("Failed to send a broadcast for receiver %s",
+                        key.ToString().c_str());
+                    return false;
                 }
             },
             [this](const int& uid, const vector<int64_t>& activeConfigs) {
-                auto receiver = mConfigManager->GetActiveConfigsChangedReceiver(uid);
-                sp<IStatsCompanionService> sc = getStatsCompanionService();
-                if (sc == nullptr) {
-                    VLOG("Could not access statsCompanion");
-                    return false;
-                } else if (receiver == nullptr) {
+                sp<IPendingIntentRef> receiver =
+                    mConfigManager->GetActiveConfigsChangedReceiver(uid);
+                if (receiver == nullptr) {
                     VLOG("Could not find receiver for uid %d", uid);
                     return false;
-                } else {
-                    sc->sendActiveConfigsChangedBroadcast(receiver, activeConfigs);
+                } else if (receiver->sendActiveConfigsChangedBroadcast(activeConfigs).isOk()) {
                     VLOG("StatsService::active configs broadcast succeeded for uid %d" , uid);
                     return true;
+                } else {
+                    VLOG("StatsService::active configs broadcast failed for uid %d" , uid);
+                    return false;
                 }
             });
 
@@ -574,18 +573,19 @@
         return UNKNOWN_ERROR;
     }
     ConfigKey key(uid, StrToInt64(name));
-    auto receiver = mConfigManager->GetConfigReceiver(key);
-    sp<IStatsCompanionService> sc = getStatsCompanionService();
-    if (sc == nullptr) {
-        VLOG("Could not access statsCompanion");
-    } else if (receiver == nullptr) {
-        VLOG("Could not find receiver for %s, %s", args[1].c_str(), args[2].c_str())
-    } else {
-        sc->sendDataBroadcast(receiver, mProcessor->getLastReportTimeNs(key));
+    sp<IPendingIntentRef> receiver = mConfigManager->GetConfigReceiver(key);
+    if (receiver == nullptr) {
+        VLOG("Could not find receiver for %s, %s", args[1].c_str(), args[2].c_str());
+        return UNKNOWN_ERROR;
+    } else if (receiver->sendDataBroadcast(
+               mProcessor->getLastReportTimeNs(key)).isOk()) {
         VLOG("StatsService::trigger broadcast succeeded to %s, %s", args[1].c_str(),
              args[2].c_str());
+    } else {
+        VLOG("StatsService::trigger broadcast failed to %s, %s", args[1].c_str(),
+             args[2].c_str());
+        return UNKNOWN_ERROR;
     }
-
     return NO_ERROR;
 }
 
@@ -629,15 +629,15 @@
             }
         }
     }
-    auto receiver = mConfigManager->GetActiveConfigsChangedReceiver(uid);
-    sp<IStatsCompanionService> sc = getStatsCompanionService();
-    if (sc == nullptr) {
-        VLOG("Could not access statsCompanion");
-    } else if (receiver == nullptr) {
+    sp<IPendingIntentRef> receiver = mConfigManager->GetActiveConfigsChangedReceiver(uid);
+    if (receiver == nullptr) {
         VLOG("Could not find receiver for uid %d", uid);
-    } else {
-        sc->sendActiveConfigsChangedBroadcast(receiver, configIds);
+        return UNKNOWN_ERROR;
+    } else if (receiver->sendActiveConfigsChangedBroadcast(configIds).isOk()) {
         VLOG("StatsService::trigger active configs changed broadcast succeeded for uid %d" , uid);
+    } else {
+        VLOG("StatsService::trigger active configs changed broadcast failed for uid %d", uid);
+        return UNKNOWN_ERROR;
     }
     return NO_ERROR;
 }
@@ -1111,7 +1111,6 @@
     mPullerManager->SetStatsCompanionService(statsCompanion);
     mAnomalyAlarmMonitor->setStatsCompanionService(statsCompanion);
     mPeriodicAlarmMonitor->setStatsCompanionService(statsCompanion);
-    SubscriberReporter::getInstance().setStatsCompanionService(statsCompanion);
     return Status::ok();
 }
 
@@ -1185,23 +1184,21 @@
     return true;
 }
 
-Status StatsService::removeDataFetchOperation(int64_t key, const String16& packageName) {
-    ENFORCE_DUMP_AND_USAGE_STATS(packageName);
-
-    IPCThreadState* ipc = IPCThreadState::self();
-    ConfigKey configKey(ipc->getCallingUid(), key);
+Status StatsService::removeDataFetchOperation(int64_t key,
+                                              const int32_t callingUid) {
+    ENFORCE_UID(AID_SYSTEM);
+    ConfigKey configKey(callingUid, key);
     mConfigManager->RemoveConfigReceiver(configKey);
     return Status::ok();
 }
 
 Status StatsService::setDataFetchOperation(int64_t key,
-                                           const sp<android::IBinder>& intentSender,
-                                           const String16& packageName) {
-    ENFORCE_DUMP_AND_USAGE_STATS(packageName);
+                                           const sp<IPendingIntentRef>& pir,
+                                           const int32_t callingUid) {
+    ENFORCE_UID(AID_SYSTEM);
 
-    IPCThreadState* ipc = IPCThreadState::self();
-    ConfigKey configKey(ipc->getCallingUid(), key);
-    mConfigManager->SetConfigReceiver(configKey, intentSender);
+    ConfigKey configKey(callingUid, key);
+    mConfigManager->SetConfigReceiver(configKey, pir);
     if (StorageManager::hasConfigMetricsReport(configKey)) {
         VLOG("StatsService::setDataFetchOperation marking configKey %s to dump reports on disk",
              configKey.ToString().c_str());
@@ -1210,27 +1207,24 @@
     return Status::ok();
 }
 
-Status StatsService::setActiveConfigsChangedOperation(const sp<android::IBinder>& intentSender,
-                                                      const String16& packageName,
+Status StatsService::setActiveConfigsChangedOperation(const sp<IPendingIntentRef>& pir,
+                                                      const int32_t callingUid,
                                                       vector<int64_t>* output) {
-    ENFORCE_DUMP_AND_USAGE_STATS(packageName);
+    ENFORCE_UID(AID_SYSTEM);
 
-    IPCThreadState* ipc = IPCThreadState::self();
-    int uid = ipc->getCallingUid();
-    mConfigManager->SetActiveConfigsChangedReceiver(uid, intentSender);
+    mConfigManager->SetActiveConfigsChangedReceiver(callingUid, pir);
     if (output != nullptr) {
-        mProcessor->GetActiveConfigs(uid, *output);
+        mProcessor->GetActiveConfigs(callingUid, *output);
     } else {
         ALOGW("StatsService::setActiveConfigsChanged output was nullptr");
     }
     return Status::ok();
 }
 
-Status StatsService::removeActiveConfigsChangedOperation(const String16& packageName) {
-    ENFORCE_DUMP_AND_USAGE_STATS(packageName);
+Status StatsService::removeActiveConfigsChangedOperation(const int32_t callingUid) {
+    ENFORCE_UID(AID_SYSTEM);
 
-    IPCThreadState* ipc = IPCThreadState::self();
-    mConfigManager->RemoveActiveConfigsChangedReceiver(ipc->getCallingUid());
+    mConfigManager->RemoveActiveConfigsChangedReceiver(callingUid);
     return Status::ok();
 }
 
@@ -1246,26 +1240,24 @@
 
 Status StatsService::setBroadcastSubscriber(int64_t configId,
                                             int64_t subscriberId,
-                                            const sp<android::IBinder>& intentSender,
-                                            const String16& packageName) {
-    ENFORCE_DUMP_AND_USAGE_STATS(packageName);
+                                            const sp<IPendingIntentRef>& pir,
+                                            const int32_t callingUid) {
+    ENFORCE_UID(AID_SYSTEM);
 
     VLOG("StatsService::setBroadcastSubscriber called.");
-    IPCThreadState* ipc = IPCThreadState::self();
-    ConfigKey configKey(ipc->getCallingUid(), configId);
+    ConfigKey configKey(callingUid, configId);
     SubscriberReporter::getInstance()
-            .setBroadcastSubscriber(configKey, subscriberId, intentSender);
+            .setBroadcastSubscriber(configKey, subscriberId, pir);
     return Status::ok();
 }
 
 Status StatsService::unsetBroadcastSubscriber(int64_t configId,
                                               int64_t subscriberId,
-                                              const String16& packageName) {
-    ENFORCE_DUMP_AND_USAGE_STATS(packageName);
+                                              const int32_t callingUid) {
+    ENFORCE_UID(AID_SYSTEM);
 
     VLOG("StatsService::unsetBroadcastSubscriber called.");
-    IPCThreadState* ipc = IPCThreadState::self();
-    ConfigKey configKey(ipc->getCallingUid(), configId);
+    ConfigKey configKey(callingUid, configId);
     SubscriberReporter::getInstance()
             .unsetBroadcastSubscriber(configKey, subscriberId);
     return Status::ok();
@@ -1631,7 +1623,6 @@
     }
     mAnomalyAlarmMonitor->setStatsCompanionService(nullptr);
     mPeriodicAlarmMonitor->setStatsCompanionService(nullptr);
-    SubscriberReporter::getInstance().setStatsCompanionService(nullptr);
     mPullerManager->SetStatsCompanionService(nullptr);
 }
 
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index de55ca9..0565f3c 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -30,6 +30,7 @@
 #include <android/frameworks/stats/1.0/IStats.h>
 #include <android/frameworks/stats/1.0/types.h>
 #include <android/os/BnStatsd.h>
+#include <android/os/IPendingIntentRef.h>
 #include <android/os/IStatsCompanionService.h>
 #include <android/os/IStatsd.h>
 #include <binder/IResultReceiver.h>
@@ -121,26 +122,26 @@
      * Binder call to let clients register the data fetch operation for a configuration.
      */
     virtual Status setDataFetchOperation(int64_t key,
-                                         const sp<android::IBinder>& intentSender,
-                                         const String16& packageName) override;
+                                         const sp<IPendingIntentRef>& pir,
+                                         const int32_t callingUid) override;
 
     /**
      * Binder call to remove the data fetch operation for the specified config key.
      */
     virtual Status removeDataFetchOperation(int64_t key,
-                                            const String16& packageName) override;
+                                            const int32_t callingUid) override;
 
     /**
      * Binder call to let clients register the active configs changed operation.
      */
-    virtual Status setActiveConfigsChangedOperation(const sp<android::IBinder>& intentSender,
-                                                    const String16& packageName,
+    virtual Status setActiveConfigsChangedOperation(const sp<IPendingIntentRef>& pir,
+                                                    const int32_t callingUid,
                                                     vector<int64_t>* output) override;
 
     /**
      * Binder call to remove the active configs changed operation for the specified package..
      */
-    virtual Status removeActiveConfigsChangedOperation(const String16& packageName) override;
+    virtual Status removeActiveConfigsChangedOperation(const int32_t callingUid) override;
     /**
      * Binder call to allow clients to remove the specified configuration.
      */
@@ -148,20 +149,19 @@
                                        const String16& packageName) override;
 
     /**
-     * Binder call to associate the given config's subscriberId with the given intentSender.
-     * intentSender must be convertible into an IntentSender (in Java) using IntentSender(IBinder).
+     * Binder call to associate the given config's subscriberId with the given pendingIntentRef.
      */
     virtual Status setBroadcastSubscriber(int64_t configId,
                                           int64_t subscriberId,
-                                          const sp<android::IBinder>& intentSender,
-                                          const String16& packageName) override;
+                                          const sp<IPendingIntentRef>& pir,
+                                          const int32_t callingUid) override;
 
     /**
-     * Binder call to unassociate the given config's subscriberId with any intentSender.
+     * Binder call to unassociate the given config's subscriberId with any pendingIntentRef.
      */
     virtual Status unsetBroadcastSubscriber(int64_t configId,
                                             int64_t subscriberId,
-                                            const String16& packageName) override;
+                                            const int32_t callingUid) override;
 
     /** Inform statsCompanion that statsd is ready. */
     virtual void sayHiToStatsCompanion();
diff --git a/cmds/statsd/src/config/ConfigManager.cpp b/cmds/statsd/src/config/ConfigManager.cpp
index fc949b4..55d73c1 100644
--- a/cmds/statsd/src/config/ConfigManager.cpp
+++ b/cmds/statsd/src/config/ConfigManager.cpp
@@ -46,6 +46,41 @@
 using android::base::StringPrintf;
 using std::unique_ptr;
 
+class ConfigReceiverDeathRecipient : public android::IBinder::DeathRecipient {
+    public:
+        ConfigReceiverDeathRecipient(sp<ConfigManager> configManager, const ConfigKey& configKey):
+            mConfigManager(configManager),
+            mConfigKey(configKey) {}
+        ~ConfigReceiverDeathRecipient() override = default;
+    private:
+        sp<ConfigManager> mConfigManager;
+        ConfigKey mConfigKey;
+
+    void binderDied(const android::wp<android::IBinder>& who) override {
+        if (IInterface::asBinder(mConfigManager->GetConfigReceiver(mConfigKey)) == who.promote()) {
+             mConfigManager->RemoveConfigReceiver(mConfigKey);
+        }
+    }
+};
+
+class ActiveConfigChangedReceiverDeathRecipient : public android::IBinder::DeathRecipient {
+    public:
+        ActiveConfigChangedReceiverDeathRecipient(sp<ConfigManager> configManager, const int uid):
+            mConfigManager(configManager),
+            mUid(uid) {}
+        ~ActiveConfigChangedReceiverDeathRecipient() override = default;
+    private:
+        sp<ConfigManager> mConfigManager;
+        int mUid;
+
+    void binderDied(const android::wp<android::IBinder>& who) override {
+        if (IInterface::asBinder(mConfigManager->GetActiveConfigsChangedReceiver(mUid))
+              == who.promote()) {
+            mConfigManager->RemoveActiveConfigsChangedReceiver(mUid);
+        }
+    }
+};
+
 ConfigManager::ConfigManager() {
 }
 
@@ -118,9 +153,11 @@
     }
 }
 
-void ConfigManager::SetConfigReceiver(const ConfigKey& key, const sp<IBinder>& intentSender) {
+void ConfigManager::SetConfigReceiver(const ConfigKey& key,
+                                      const sp<IPendingIntentRef>& pir) {
     lock_guard<mutex> lock(mMutex);
-    mConfigReceivers[key] = intentSender;
+    mConfigReceivers[key] = pir;
+    IInterface::asBinder(pir)->linkToDeath(new ConfigReceiverDeathRecipient(this, key));
 }
 
 void ConfigManager::RemoveConfigReceiver(const ConfigKey& key) {
@@ -129,9 +166,11 @@
 }
 
 void ConfigManager::SetActiveConfigsChangedReceiver(const int uid,
-                                                    const sp<IBinder>& intentSender) {
+                                                    const sp<IPendingIntentRef>& pir) {
     lock_guard<mutex> lock(mMutex);
-    mActiveConfigsChangedReceivers[uid] = intentSender;
+    mActiveConfigsChangedReceivers[uid] = pir;
+    IInterface::asBinder(pir)->linkToDeath(
+        new ActiveConfigChangedReceiverDeathRecipient(this, uid));
 }
 
 void ConfigManager::RemoveActiveConfigsChangedReceiver(const int uid) {
@@ -266,7 +305,7 @@
     return ret;
 }
 
-const sp<android::IBinder> ConfigManager::GetConfigReceiver(const ConfigKey& key) const {
+const sp<IPendingIntentRef> ConfigManager::GetConfigReceiver(const ConfigKey& key) const {
     lock_guard<mutex> lock(mMutex);
 
     auto it = mConfigReceivers.find(key);
@@ -277,7 +316,7 @@
     }
 }
 
-const sp<android::IBinder> ConfigManager::GetActiveConfigsChangedReceiver(const int uid) const {
+const sp<IPendingIntentRef> ConfigManager::GetActiveConfigsChangedReceiver(const int uid) const {
     lock_guard<mutex> lock(mMutex);
 
     auto it = mActiveConfigsChangedReceivers.find(uid);
diff --git a/cmds/statsd/src/config/ConfigManager.h b/cmds/statsd/src/config/ConfigManager.h
index c064a51..88e864a 100644
--- a/cmds/statsd/src/config/ConfigManager.h
+++ b/cmds/statsd/src/config/ConfigManager.h
@@ -16,10 +16,10 @@
 
 #pragma once
 
-#include "binder/IBinder.h"
 #include "config/ConfigKey.h"
 #include "config/ConfigListener.h"
 
+#include <android/os/IPendingIntentRef.h>
 #include <map>
 #include <mutex>
 #include <set>
@@ -64,12 +64,12 @@
     /**
      * Sets the broadcast receiver for a configuration key.
      */
-    void SetConfigReceiver(const ConfigKey& key, const sp<IBinder>& intentSender);
+    void SetConfigReceiver(const ConfigKey& key, const sp<IPendingIntentRef>& pir);
 
     /**
      * Returns the package name and class name representing the broadcast receiver for this config.
      */
-    const sp<android::IBinder> GetConfigReceiver(const ConfigKey& key) const;
+    const sp<IPendingIntentRef> GetConfigReceiver(const ConfigKey& key) const;
 
     /**
      * Returns all config keys registered.
@@ -85,13 +85,13 @@
      * Sets the broadcast receiver that is notified whenever the list of active configs
      * changes for this uid.
      */
-    void SetActiveConfigsChangedReceiver(const int uid, const sp<IBinder>& intentSender);
+    void SetActiveConfigsChangedReceiver(const int uid, const sp<IPendingIntentRef>& pir);
 
     /**
      * Returns the broadcast receiver for active configs changed for this uid.
      */
 
-    const sp<IBinder> GetActiveConfigsChangedReceiver(const int uid) const;
+    const sp<IPendingIntentRef> GetActiveConfigsChangedReceiver(const int uid) const;
 
     /**
      * Erase any active configs changed broadcast receiver associated with this uid.
@@ -141,16 +141,15 @@
     std::map<int, std::set<ConfigKey>> mConfigs;
 
     /**
-     * Each config key can be subscribed by up to one receiver, specified as IBinder from
-     * PendingIntent.
+     * Each config key can be subscribed by up to one receiver, specified as IPendingIntentRef.
      */
-    std::map<ConfigKey, sp<android::IBinder>> mConfigReceivers;
+    std::map<ConfigKey, sp<IPendingIntentRef>> mConfigReceivers;
 
     /**
      * Each uid can be subscribed by up to one receiver to notify that the list of active configs
-     * for this uid has changed. The receiver is specified as IBinder from PendingIntent.
+     * for this uid has changed. The receiver is specified as IPendingIntentRef.
      */
-     std::map<int, sp<android::IBinder>> mActiveConfigsChangedReceivers;
+     std::map<int, sp<IPendingIntentRef>> mActiveConfigsChangedReceivers;
 
     /**
      * The ConfigListeners that will be told about changes.
diff --git a/cmds/statsd/src/subscriber/SubscriberReporter.cpp b/cmds/statsd/src/subscriber/SubscriberReporter.cpp
index 25d2257..a9a105f 100644
--- a/cmds/statsd/src/subscriber/SubscriberReporter.cpp
+++ b/cmds/statsd/src/subscriber/SubscriberReporter.cpp
@@ -19,7 +19,6 @@
 
 #include "SubscriberReporter.h"
 
-using android::IBinder;
 using std::lock_guard;
 using std::unordered_map;
 
@@ -29,12 +28,32 @@
 
 using std::vector;
 
+class BroadcastSubscriberDeathRecipient : public android::IBinder::DeathRecipient {
+    public:
+        BroadcastSubscriberDeathRecipient(const ConfigKey& configKey, int64_t subscriberId):
+            mConfigKey(configKey),
+            mSubscriberId(subscriberId) {}
+        ~BroadcastSubscriberDeathRecipient() override = default;
+    private:
+        ConfigKey mConfigKey;
+        int64_t mSubscriberId;
+
+    void binderDied(const android::wp<android::IBinder>& who) override {
+        if (IInterface::asBinder(SubscriberReporter::getInstance().getBroadcastSubscriber(
+              mConfigKey, mSubscriberId)) == who.promote()) {
+            SubscriberReporter::getInstance().unsetBroadcastSubscriber(mConfigKey, mSubscriberId);
+        }
+    }
+};
+
 void SubscriberReporter::setBroadcastSubscriber(const ConfigKey& configKey,
                                                 int64_t subscriberId,
-                                                const sp<IBinder>& intentSender) {
+                                                const sp<IPendingIntentRef>& pir) {
     VLOG("SubscriberReporter::setBroadcastSubscriber called.");
     lock_guard<std::mutex> lock(mLock);
-    mIntentMap[configKey][subscriberId] = intentSender;
+    mIntentMap[configKey][subscriberId] = pir;
+    IInterface::asBinder(pir)->linkToDeath(
+        new BroadcastSubscriberDeathRecipient(configKey, subscriberId));
 }
 
 void SubscriberReporter::unsetBroadcastSubscriber(const ConfigKey& configKey,
@@ -97,18 +116,13 @@
     sendBroadcastLocked(it2->second, configKey, subscription, cookies, dimKey);
 }
 
-void SubscriberReporter::sendBroadcastLocked(const sp<IBinder>& intentSender,
+void SubscriberReporter::sendBroadcastLocked(const sp<IPendingIntentRef>& pir,
                                              const ConfigKey& configKey,
                                              const Subscription& subscription,
                                              const vector<String16>& cookies,
                                              const MetricDimensionKey& dimKey) const {
     VLOG("SubscriberReporter::sendBroadcastLocked called.");
-    if (mStatsCompanionService == nullptr) {
-        ALOGW("Failed to send subscriber broadcast: could not access StatsCompanionService.");
-        return;
-    }
-    mStatsCompanionService->sendSubscriberBroadcast(
-            intentSender,
+    pir->sendSubscriberBroadcast(
             configKey.GetUid(),
             configKey.GetId(),
             subscription.id(),
@@ -117,6 +131,20 @@
             getStatsDimensionsValue(dimKey.getDimensionKeyInWhat()));
 }
 
+sp<IPendingIntentRef> SubscriberReporter::getBroadcastSubscriber(const ConfigKey& configKey,
+                                                                 int64_t subscriberId) {
+    lock_guard<std::mutex> lock(mLock);
+    auto subscriberMapIt = mIntentMap.find(configKey);
+    if (subscriberMapIt == mIntentMap.end()) {
+        return nullptr;
+    }
+    auto pirMapIt = subscriberMapIt->second.find(subscriberId);
+    if (pirMapIt == subscriberMapIt->second.end()) {
+        return nullptr;
+    }
+    return pirMapIt->second;
+}
+
 void getStatsDimensionsValueHelper(const vector<FieldValue>& dims, size_t* index, int depth,
                                    int prefix, vector<StatsDimensionsValue>* output) {
     size_t count = dims.size();
diff --git a/cmds/statsd/src/subscriber/SubscriberReporter.h b/cmds/statsd/src/subscriber/SubscriberReporter.h
index 2a7f771..8ccc8ee 100644
--- a/cmds/statsd/src/subscriber/SubscriberReporter.h
+++ b/cmds/statsd/src/subscriber/SubscriberReporter.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <android/os/IPendingIntentRef.h>
 #include <android/os/IStatsCompanionService.h>
 #include <utils/RefBase.h>
 
@@ -47,23 +48,11 @@
     void operator=(SubscriberReporter const&) = delete;
 
     /**
-     * Tells SubscriberReporter what IStatsCompanionService to use.
-     * May be nullptr, but SubscriberReporter will not send broadcasts for any calls
-     * to alertBroadcastSubscriber that occur while nullptr.
-     */
-    void setStatsCompanionService(sp<IStatsCompanionService> statsCompanionService) {
-        std::lock_guard<std::mutex> lock(mLock);
-        sp<IStatsCompanionService> tmpForLock = mStatsCompanionService;
-        mStatsCompanionService = statsCompanionService;
-    }
-
-    /**
      * Stores the given intentSender, associating it with the given (configKey, subscriberId) pair.
-     * intentSender must be convertible into an IntentSender (in Java) using IntentSender(IBinder).
      */
     void setBroadcastSubscriber(const ConfigKey& configKey,
                                 int64_t subscriberId,
-                                const sp<android::IBinder>& intentSender);
+                                const sp<IPendingIntentRef>& pir);
 
     /**
      * Erases any intentSender information from the given (configKey, subscriberId) pair.
@@ -82,6 +71,8 @@
                                   const Subscription& subscription,
                                   const MetricDimensionKey& dimKey) const;
 
+    sp<IPendingIntentRef> getBroadcastSubscriber(const ConfigKey& configKey, int64_t subscriberId);
+
     static StatsDimensionsValue getStatsDimensionsValue(const HashableDimensionKey& dim);
 
 private:
@@ -92,15 +83,15 @@
     /** Binder interface for communicating with StatsCompanionService. */
     sp<IStatsCompanionService> mStatsCompanionService = nullptr;
 
-    /** Maps <ConfigKey, SubscriberId> -> IBinder (which represents an IIntentSender). */
+    /** Maps <ConfigKey, SubscriberId> -> IPendingIntentRef (which represents a PendingIntent). */
     std::unordered_map<ConfigKey,
-            std::unordered_map<int64_t, sp<android::IBinder>>> mIntentMap;
+            std::unordered_map<int64_t, sp<IPendingIntentRef>>> mIntentMap;
 
     /**
      * Sends a broadcast via the given intentSender (using mStatsCompanionService), along
      * with the information in the other parameters.
      */
-    void sendBroadcastLocked(const sp<android::IBinder>& intentSender,
+    void sendBroadcastLocked(const sp<IPendingIntentRef>& pir,
                              const ConfigKey& configKey,
                              const Subscription& subscription,
                              const std::vector<String16>& cookies,
diff --git a/core/java/android/app/InstantAppResolverService.java b/core/java/android/app/InstantAppResolverService.java
index a413c60..0cd030e 100644
--- a/core/java/android/app/InstantAppResolverService.java
+++ b/core/java/android/app/InstantAppResolverService.java
@@ -35,6 +35,7 @@
 import android.util.Log;
 import android.util.Slog;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.SomeArgs;
 
 import java.util.Arrays;
@@ -297,7 +298,10 @@
     public static final class InstantAppResolutionCallback {
         private final IRemoteCallback mCallback;
         private final int mSequence;
-        InstantAppResolutionCallback(int sequence, IRemoteCallback callback) {
+
+        /** @hide **/
+        @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+        public InstantAppResolutionCallback(int sequence, IRemoteCallback callback) {
             mCallback = callback;
             mSequence = sequence;
         }
diff --git a/core/java/android/app/StatsManager.java b/core/java/android/app/StatsManager.java
index b9893aa..83d1de6 100644
--- a/core/java/android/app/StatsManager.java
+++ b/core/java/android/app/StatsManager.java
@@ -255,18 +255,17 @@
             throws StatsUnavailableException {
         synchronized (sLock) {
             try {
-                IStatsd service = getIStatsdLocked();
+                IStatsManagerService service = getIStatsManagerServiceLocked();
                 if (pendingIntent != null) {
-                    // Extracts IIntentSender from the PendingIntent and turns it into an IBinder.
-                    IBinder intentSender = pendingIntent.getTarget().asBinder();
-                    service.setBroadcastSubscriber(configKey, subscriberId, intentSender,
+                    service.setBroadcastSubscriber(configKey, subscriberId, pendingIntent,
                             mContext.getOpPackageName());
                 } else {
                     service.unsetBroadcastSubscriber(configKey, subscriberId,
                             mContext.getOpPackageName());
                 }
             } catch (RemoteException e) {
-                Slog.e(TAG, "Failed to connect to statsd when adding broadcast subscriber", e);
+                Slog.e(TAG, "Failed to connect to statsmanager when adding broadcast subscriber",
+                        e);
                 throw new StatsUnavailableException("could not connect", e);
             } catch (SecurityException e) {
                 throw new StatsUnavailableException(e.getMessage(), e);
@@ -309,18 +308,16 @@
             throws StatsUnavailableException {
         synchronized (sLock) {
             try {
-                IStatsd service = getIStatsdLocked();
+                IStatsManagerService service = getIStatsManagerServiceLocked();
                 if (pendingIntent == null) {
                     service.removeDataFetchOperation(configKey, mContext.getOpPackageName());
                 } else {
-                    // Extracts IIntentSender from the PendingIntent and turns it into an IBinder.
-                    IBinder intentSender = pendingIntent.getTarget().asBinder();
-                    service.setDataFetchOperation(configKey, intentSender,
+                    service.setDataFetchOperation(configKey, pendingIntent,
                             mContext.getOpPackageName());
                 }
 
             } catch (RemoteException e) {
-                Slog.e(TAG, "Failed to connect to statsd when registering data listener.");
+                Slog.e(TAG, "Failed to connect to statsmanager when registering data listener.");
                 throw new StatsUnavailableException("could not connect", e);
             } catch (SecurityException e) {
                 throw new StatsUnavailableException(e.getMessage(), e);
@@ -347,20 +344,18 @@
             throws StatsUnavailableException {
         synchronized (sLock) {
             try {
-                IStatsd service = getIStatsdLocked();
+                IStatsManagerService service = getIStatsManagerServiceLocked();
                 if (pendingIntent == null) {
                     service.removeActiveConfigsChangedOperation(mContext.getOpPackageName());
                     return new long[0];
                 } else {
-                    // Extracts IIntentSender from the PendingIntent and turns it into an IBinder.
-                    IBinder intentSender = pendingIntent.getTarget().asBinder();
-                    return service.setActiveConfigsChangedOperation(intentSender,
+                    return service.setActiveConfigsChangedOperation(pendingIntent,
                             mContext.getOpPackageName());
                 }
 
             } catch (RemoteException e) {
-                Slog.e(TAG,
-                        "Failed to connect to statsd when registering active configs listener.");
+                Slog.e(TAG, "Failed to connect to statsmanager "
+                        + "when registering active configs listener.");
                 throw new StatsUnavailableException("could not connect", e);
             } catch (SecurityException e) {
                 throw new StatsUnavailableException(e.getMessage(), e);
diff --git a/core/java/android/app/TEST_MAPPING b/core/java/android/app/TEST_MAPPING
index c585b5f..7b45b72 100644
--- a/core/java/android/app/TEST_MAPPING
+++ b/core/java/android/app/TEST_MAPPING
@@ -48,6 +48,10 @@
                 }
             ],
             "file_patterns": ["INotificationManager\\.aidl"]
+        },
+        {
+            "name": "FrameworksInstantAppResolverTests",
+            "file_patterns": ["(/|^)InstantAppResolve[^/]*"]
         }
     ],
     "postsubmit": [
diff --git a/core/java/android/app/role/RoleManager.java b/core/java/android/app/role/RoleManager.java
index 61eeacc..ea66fd47 100644
--- a/core/java/android/app/role/RoleManager.java
+++ b/core/java/android/app/role/RoleManager.java
@@ -630,9 +630,12 @@
      * {@link Manifest.permission#OBSERVE_ROLE_HOLDERS}, as required by
      * {@link android.provider.Telephony.Sms#getDefaultSmsPackage(Context)}
      *
+     * @param userId The user ID to get the default SMS package for.
+     * @return the package name of the default SMS app, or {@code null} if not configured.
      * @hide
      */
     @Nullable
+    @SystemApi
     public String getDefaultSmsPackage(@UserIdInt int userId) {
         try {
             return mService.getDefaultSmsPackage(userId);
diff --git a/core/java/android/content/pm/TEST_MAPPING b/core/java/android/content/pm/TEST_MAPPING
index df4ae09..0549c34 100644
--- a/core/java/android/content/pm/TEST_MAPPING
+++ b/core/java/android/content/pm/TEST_MAPPING
@@ -9,5 +9,11 @@
     {
       "path": "system/apex/tests"
     }
+  ],
+  "presubmit": [
+    {
+      "name": "FrameworksInstantAppResolverTests",
+      "file_patterns": ["(/|^)InstantApp[^/]*"]
+    }
   ]
 }
diff --git a/core/java/android/content/pm/parsing/ComponentParseUtils.java b/core/java/android/content/pm/parsing/ComponentParseUtils.java
index 7b24d3d..5956857 100644
--- a/core/java/android/content/pm/parsing/ComponentParseUtils.java
+++ b/core/java/android/content/pm/parsing/ComponentParseUtils.java
@@ -465,7 +465,8 @@
         }
 
         public void setPermission(String permission) {
-            this.permission = TextUtils.safeIntern(permission);
+            // Empty string must be converted to null
+            this.permission = TextUtils.isEmpty(permission) ? null : permission.intern();
         }
 
         public String getPermission() {
@@ -842,7 +843,9 @@
         }
 
         public void setReadPermission(String readPermission) {
-            this.readPermission = TextUtils.safeIntern(readPermission);
+            // Empty string must be converted to null
+            this.readPermission = TextUtils.isEmpty(readPermission)
+                    ? null : readPermission.intern();
         }
 
         public String getReadPermission() {
@@ -850,7 +853,9 @@
         }
 
         public void setWritePermission(String writePermission) {
-            this.writePermission = TextUtils.safeIntern(writePermission);
+            // Empty string must be converted to null
+            this.writePermission = TextUtils.isEmpty(writePermission)
+                    ? null : writePermission.intern();
         }
 
         public String getWritePermission() {
diff --git a/core/java/android/view/InsetsSource.java b/core/java/android/view/InsetsSource.java
index 1a33ea9..324d562 100644
--- a/core/java/android/view/InsetsSource.java
+++ b/core/java/android/view/InsetsSource.java
@@ -41,6 +41,7 @@
     public InsetsSource(@InternalInsetsType int type) {
         mType = type;
         mFrame = new Rect();
+        mVisible = InsetsState.getDefaultVisibility(type);
     }
 
     public InsetsSource(InsetsSource other) {
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index 179828c..a86d702 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -35,6 +35,7 @@
 import com.android.server.NetworkManagementSocketTagger;
 
 import dalvik.system.RuntimeHooks;
+import dalvik.system.ThreadPrioritySetter;
 import dalvik.system.VMRuntime;
 
 import libcore.content.type.MimeMap;
@@ -204,6 +205,7 @@
      */
     public static void preForkInit() {
         if (DEBUG) Slog.d(TAG, "Entered preForkInit.");
+        RuntimeHooks.setThreadPrioritySetter(new RuntimeThreadPrioritySetter());
         RuntimeInit.enableDdms();
         // TODO(b/142019040#comment13): Decide whether to load the default instance eagerly, i.e.
         // MimeMap.setDefault(DefaultMimeMapFactory.create());
@@ -216,6 +218,35 @@
         MimeMap.setDefaultSupplier(DefaultMimeMapFactory::create);
     }
 
+    private static class RuntimeThreadPrioritySetter implements ThreadPrioritySetter {
+        // Should remain consistent with kNiceValues[] in system/libartpalette/palette_android.cc
+        private static final int[] NICE_VALUES = {
+            Process.THREAD_PRIORITY_LOWEST,  // 1 (MIN_PRIORITY)
+            Process.THREAD_PRIORITY_BACKGROUND + 6,
+            Process.THREAD_PRIORITY_BACKGROUND + 3,
+            Process.THREAD_PRIORITY_BACKGROUND,
+            Process.THREAD_PRIORITY_DEFAULT,  // 5 (NORM_PRIORITY)
+            Process.THREAD_PRIORITY_DEFAULT - 2,
+            Process.THREAD_PRIORITY_DEFAULT - 4,
+            Process.THREAD_PRIORITY_URGENT_DISPLAY + 3,
+            Process.THREAD_PRIORITY_URGENT_DISPLAY + 2,
+            Process.THREAD_PRIORITY_URGENT_DISPLAY  // 10 (MAX_PRIORITY)
+        };
+
+        @Override
+        public void setPriority(int priority) {
+            // Check NICE_VALUES[] length first.
+            if (NICE_VALUES.length != (1 + Thread.MAX_PRIORITY - Thread.MIN_PRIORITY)) {
+                throw new AssertionError("Unexpected NICE_VALUES.length=" + NICE_VALUES.length);
+            }
+            // Priority should be in the range of MIN_PRIORITY (1) to MAX_PRIORITY (10).
+            if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {
+                throw new IllegalArgumentException("Priority out of range: " + priority);
+            }
+            Process.setThreadPriority(NICE_VALUES[priority - Thread.MIN_PRIORITY]);
+        }
+    }
+
     @UnsupportedAppUsage
     protected static final void commonInit() {
         if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");
diff --git a/core/jni/android_view_DisplayEventReceiver.cpp b/core/jni/android_view_DisplayEventReceiver.cpp
index 3531cf2..7daefd3 100644
--- a/core/jni/android_view_DisplayEventReceiver.cpp
+++ b/core/jni/android_view_DisplayEventReceiver.cpp
@@ -62,7 +62,7 @@
     void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count) override;
     void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override;
     void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId,
-                               int32_t configId) override;
+                               int32_t configId, nsecs_t vsyncPeriod) override;
 };
 
 
@@ -118,24 +118,23 @@
     mMessageQueue->raiseAndClearException(env, "dispatchHotplug");
 }
 
-void NativeDisplayEventReceiver::dispatchConfigChanged(nsecs_t timestamp,
-                                                       PhysicalDisplayId displayId,
-                                                       int32_t configId) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+void NativeDisplayEventReceiver::dispatchConfigChanged(
+    nsecs_t timestamp, PhysicalDisplayId displayId, int32_t configId, nsecs_t) {
+  JNIEnv* env = AndroidRuntime::getJNIEnv();
 
-    ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
-    if (receiverObj.get()) {
-        ALOGV("receiver %p ~ Invoking config changed handler.", this);
-        env->CallVoidMethod(receiverObj.get(),
-                            gDisplayEventReceiverClassInfo.dispatchConfigChanged,
-                            timestamp, displayId, configId);
-        ALOGV("receiver %p ~ Returned from config changed handler.", this);
-    }
+  ScopedLocalRef<jobject> receiverObj(env,
+                                      jniGetReferent(env, mReceiverWeakGlobal));
+  if (receiverObj.get()) {
+    ALOGV("receiver %p ~ Invoking config changed handler.", this);
+    env->CallVoidMethod(receiverObj.get(),
+                        gDisplayEventReceiverClassInfo.dispatchConfigChanged,
+                        timestamp, displayId, configId);
+    ALOGV("receiver %p ~ Returned from config changed handler.", this);
+  }
 
-    mMessageQueue->raiseAndClearException(env, "dispatchConfigChanged");
+  mMessageQueue->raiseAndClearException(env, "dispatchConfigChanged");
 }
 
-
 static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
         jobject messageQueueObj, jint vsyncSource, jint configChanged) {
     sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
diff --git a/core/tests/InstantAppResolverTests/Android.bp b/core/tests/InstantAppResolverTests/Android.bp
new file mode 100644
index 0000000..7b01010
--- /dev/null
+++ b/core/tests/InstantAppResolverTests/Android.bp
@@ -0,0 +1,32 @@
+//
+// 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.
+//
+
+android_test {
+    name: "FrameworksInstantAppResolverTests",
+    srcs: [ "src/**/*.kt" ],
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+    platform_apis: true,
+    static_libs: [
+        "androidx.test.ext.junit",
+        "androidx.test.rules",
+        "mockito-target-minus-junit4",
+        "truth-prebuilt",
+    ],
+    test_suites: ["device-tests"],
+}
diff --git a/core/tests/InstantAppResolverTests/AndroidManifest.xml b/core/tests/InstantAppResolverTests/AndroidManifest.xml
new file mode 100644
index 0000000..f95978b
--- /dev/null
+++ b/core/tests/InstantAppResolverTests/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.app.instantapp.resolver.test"
+    >
+
+    <application>
+        <uses-library android:name="android.test.runner"/>
+    </application>
+
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:label="InstantAppResolverTests"
+        android:targetPackage="android.app.instantapp.resolver.test"
+        />
+
+</manifest>
diff --git a/core/tests/InstantAppResolverTests/AndroidTest.xml b/core/tests/InstantAppResolverTests/AndroidTest.xml
new file mode 100644
index 0000000..fcc6344
--- /dev/null
+++ b/core/tests/InstantAppResolverTests/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+
+<configuration description="Test module config for InstantAppResolverTests">
+    <option name="test-tag" value="InstantAppResolverTests" />
+
+    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="FrameworksInstantAppResolverTests.apk" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="android.app.instantapp.resolver.test" />
+    </test>
+</configuration>
diff --git a/core/tests/InstantAppResolverTests/src/android/app/instantapp/resolver/test/ResolverServiceMethodFallbackTest.kt b/core/tests/InstantAppResolverTests/src/android/app/instantapp/resolver/test/ResolverServiceMethodFallbackTest.kt
new file mode 100644
index 0000000..2a17ef2
--- /dev/null
+++ b/core/tests/InstantAppResolverTests/src/android/app/instantapp/resolver/test/ResolverServiceMethodFallbackTest.kt
@@ -0,0 +1,174 @@
+/*
+ * 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.app.instantapp.resolver.test
+
+import android.app.InstantAppResolverService
+import android.app.InstantAppResolverService.InstantAppResolutionCallback
+import android.content.Intent
+import android.content.pm.InstantAppRequestInfo
+import android.net.Uri
+import android.os.Bundle
+import android.os.IRemoteCallback
+import android.os.UserHandle
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.ExpectedException
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+import org.mockito.Answers
+import org.mockito.Mock
+import org.mockito.Mockito.doNothing
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
+import org.mockito.MockitoAnnotations
+import java.util.UUID
+import kotlin.random.Random
+
+private typealias Method = InstantAppResolverService.(InstantAppRequestInfo) -> Unit
+
+@Suppress("max-line-length")
+@RunWith(Parameterized::class)
+class ResolverServiceMethodFallbackTest @Suppress("UNUSED_PARAMETER") constructor(
+    private val version: Int,
+    private val methodList: List<Method>,
+    private val info: InstantAppRequestInfo,
+    // Remaining only used to print human-readable test name
+    name: String,
+    isWebIntent: Boolean
+) {
+
+    companion object {
+        // Since the resolution callback class is final, mock the IRemoteCallback and have it throw
+        // a unique exception to indicate it was called.
+        class TestRemoteCallbackException : Exception()
+
+        private val testIntentWeb = Intent(Intent.ACTION_VIEW,
+                Uri.parse("https://${this::class.java.canonicalName}.com"))
+        private val testIntentNotWeb = Intent(Intent.ACTION_VIEW,
+                Uri.parse("content://${this::class.java.canonicalName}"))
+
+        private val testRemoteCallback = object : IRemoteCallback {
+            override fun sendResult(data: Bundle?) = throw TestRemoteCallbackException()
+            override fun asBinder() = throw UnsupportedOperationException()
+        }
+        private val testResolutionCallback = InstantAppResolutionCallback(0, testRemoteCallback)
+        private val testArray = IntArray(10) { Random.nextInt() }
+        private val testToken = UUID.randomUUID().toString()
+        private val testUser = UserHandle(Integer.MAX_VALUE)
+        private val testInfoWeb = InstantAppRequestInfo(testIntentWeb, testArray, testUser,
+                false, testToken)
+        private val testInfoNotWeb = InstantAppRequestInfo(testIntentNotWeb, testArray, testUser,
+                false, testToken)
+
+        // Each section defines methods versions with later definitions falling back to
+        // earlier definitions. Each block receives an [InstantAppResolverService] and invokes
+        // the appropriate version with the test data defined above.
+        private val infoOne: Method = { onGetInstantAppResolveInfo(testArray, testToken,
+                testResolutionCallback) }
+        private val infoTwo: Method = { onGetInstantAppResolveInfo(it.intent, testArray, testToken,
+                testResolutionCallback) }
+        private val infoThree: Method = { onGetInstantAppResolveInfo(it.intent, testArray, testUser,
+                testToken, testResolutionCallback) }
+        private val infoFour: Method = { onGetInstantAppResolveInfo(it, testResolutionCallback) }
+
+        private val filterOne: Method = { onGetInstantAppIntentFilter(testArray, testToken,
+                testResolutionCallback) }
+        private val filterTwo: Method = { onGetInstantAppIntentFilter(it.intent, testArray,
+                testToken, testResolutionCallback) }
+        private val filterThree: Method = { onGetInstantAppIntentFilter(it.intent, testArray,
+                testUser, testToken, testResolutionCallback) }
+        private val filterFour: Method = { onGetInstantAppIntentFilter(it, testResolutionCallback) }
+
+        private val infoList = listOf(infoOne, infoTwo, infoThree, infoFour)
+        private val filterList = listOf(filterOne, filterTwo, filterThree, filterFour)
+
+        @JvmStatic
+        @Parameterized.Parameters(name = "{3} version {0}, isWeb = {4}")
+        fun parameters(): Array<Array<*>> {
+            // Sanity check that web intent logic hasn't changed
+            assertThat(testInfoWeb.intent.isWebIntent).isTrue()
+            assertThat(testInfoNotWeb.intent.isWebIntent).isFalse()
+
+            // Declare all the possible params
+            val versions = Array(5) { it }
+            val methods = arrayOf("ResolveInfo" to infoList, "IntentFilter" to filterList)
+            val infos = arrayOf(testInfoWeb, testInfoNotWeb)
+
+            // FlatMap params into every possible combination
+            return infos.flatMap { info ->
+                methods.flatMap { (name, methods) ->
+                    versions.map { version ->
+                        arrayOf(version, methods, info, name, info.intent.isWebIntent)
+                    }
+                }
+            }.toTypedArray()
+        }
+    }
+
+    @field:Mock(answer = Answers.CALLS_REAL_METHODS)
+    lateinit var mockService: InstantAppResolverService
+
+    @get:Rule
+    val expectedException = ExpectedException.none()
+
+    @Before
+    fun setUpMocks() {
+        MockitoAnnotations.initMocks(this)
+    }
+
+    @Test
+    fun onGetInstantApp() {
+        if (version == 0) {
+            // No version of the API was implemented, so expect terminal case
+            if (info.intent.isWebIntent) {
+                // If web intent, terminal is total failure
+                expectedException.expect(IllegalStateException::class.java)
+            } else {
+                // Otherwise, terminal is a fail safe by calling [testRemoteCallback]
+                expectedException.expect(TestRemoteCallbackException::class.java)
+            }
+        } else if (version < 2 && !info.intent.isWebIntent) {
+            // Starting from v2, if resolving a non-web intent and a v2+ method isn't implemented,
+            // it fails safely by calling [testRemoteCallback]
+            expectedException.expect(TestRemoteCallbackException::class.java)
+        }
+
+        // Version 1 is the first method (index 0)
+        val methodIndex = version - 1
+
+        // Implement a method if necessary
+        methodList.getOrNull(methodIndex)?.invoke(doNothing().`when`(mockService), info)
+
+        // Call the latest API
+        methodList.last().invoke(mockService, info)
+
+        // Check all methods before implemented method are never called
+        (0 until methodIndex).forEach {
+            methodList[it].invoke(verify(mockService, never()), info)
+        }
+
+        // Check all methods from implemented method are called
+        (methodIndex until methodList.size).forEach {
+            methodList[it].invoke(verify(mockService), info)
+        }
+
+        verifyNoMoreInteractions(mockService)
+    }
+}
diff --git a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
index 2cf6ff3..7af833b 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
@@ -102,8 +102,12 @@
 
     @Test
     public void testShow() {
+
+        // Insets source starts out visible
+        mConsumer.hide();
         mConsumer.show();
         assertTrue("Consumer should be visible", mConsumer.isVisible());
+        verify(mSpyInsetsSource).setVisible(eq(false));
         verify(mSpyInsetsSource).setVisible(eq(true));
     }
 
diff --git a/core/xsd/permission.xsd b/core/xsd/permission.xsd
index 9520db7..cc01a31 100644
--- a/core/xsd/permission.xsd
+++ b/core/xsd/permission.xsd
@@ -126,12 +126,12 @@
     </xs:complexType>
     <xs:complexType name="privapp-permissions">
         <xs:sequence>
-            <xs:element name="permission" maxOccurs="unbounded">
+            <xs:element name="permission" minOccurs="0" maxOccurs="unbounded">
                 <xs:complexType>
                     <xs:attribute name="name" type="xs:string"/>
                 </xs:complexType>
             </xs:element>
-            <xs:element name="deny-permission" maxOccurs="unbounded">
+            <xs:element name="deny-permission" minOccurs="0" maxOccurs="unbounded">
                 <xs:complexType>
                     <xs:attribute name="name" type="xs:string"/>
                 </xs:complexType>
@@ -141,12 +141,12 @@
     </xs:complexType>
     <xs:complexType name="oem-permissions">
         <xs:sequence>
-            <xs:element name="permission" maxOccurs="unbounded">
+            <xs:element name="permission" minOccurs="0" maxOccurs="unbounded">
                 <xs:complexType>
                     <xs:attribute name="name" type="xs:string"/>
                 </xs:complexType>
             </xs:element>
-            <xs:element name="deny-permission" maxOccurs="unbounded">
+            <xs:element name="deny-permission" minOccurs="0" maxOccurs="unbounded">
                 <xs:complexType>
                     <xs:attribute name="name" type="xs:string"/>
                 </xs:complexType>
diff --git a/media/java/android/media/tv/tuner/FilterEvent.java b/media/java/android/media/tv/tuner/FilterEvent.java
deleted file mode 100644
index 7c165ce..0000000
--- a/media/java/android/media/tv/tuner/FilterEvent.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * 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.media.tv.tuner;
-
-import android.os.NativeHandle;
-
-/**
- * Demux filter event.
- *
- * @hide
- */
-public abstract class FilterEvent {
-
-    /**
-     * Section event.
-     */
-    public static class SectionEvent extends FilterEvent {
-        private int mTableId;
-        private int mVersion;
-        private int mSectionNum;
-        private int mDataLength;
-    }
-
-    /**
-     * Media event.
-     */
-    public static class MediaEvent extends FilterEvent {
-        private int mStreamId;
-        private boolean mIsPtsPresent;
-        private long mPts;
-        private int mDataLength;
-        private NativeHandle mHandle;
-        private boolean mIsSecureMemory;
-        private int mMpuSequenceNumber;
-        private boolean mIsPrivateData;
-        private AudioExtraMetaData mExtraMetaData;
-    }
-
-    /**
-     * PES event.
-     */
-    public static class PesEvent extends FilterEvent {
-        private int mStreamId;
-        private int mDataLength;
-        private int mMpuSequenceNumber;
-    }
-
-    /**
-     * TS record event.
-     */
-    public static class TsRecordEvent extends FilterEvent {
-        private int mTpid;
-        private int mIndexMask;
-        private long mByteNumber;
-    }
-
-    /**
-     * MMPT record event.
-     */
-    public static class MmtpRecordEvent extends FilterEvent {
-        private int mScHevcIndexMask;
-        private long mByteNumber;
-    }
-
-    /**
-     * Download event.
-     */
-    public static class DownloadEvent extends FilterEvent {
-        private int mItemId;
-        private int mMpuSequenceNumber;
-        private int mItemFragmentIndex;
-        private int mLastItemFragmentIndex;
-        private int mDataLength;
-    }
-
-    /**
-     * IP payload event.
-     */
-    public static class IpPayloadEvent extends FilterEvent {
-        private int mDataLength;
-    }
-
-    /**
-     * TEMI event.
-     */
-    public static class TemiEvent extends FilterEvent {
-        private long mPts;
-        private byte mDescrTag;
-        private byte[] mDescrData;
-    }
-
-    /**
-     *  Extra Meta Data from AD (Audio Descriptor) according to
-     *  ETSI TS 101 154 V2.1.1.
-     */
-    public static class AudioExtraMetaData {
-        private byte mAdFade;
-        private byte mAdPan;
-        private byte mVersionTextTag;
-        private byte mAdGainCenter;
-        private byte mAdGainFront;
-        private byte mAdGainSurround;
-    }
-}
diff --git a/media/java/android/media/tv/tuner/FilterSettings.java b/media/java/android/media/tv/tuner/FilterSettings.java
index 673b3d9..4ee61a8 100644
--- a/media/java/android/media/tv/tuner/FilterSettings.java
+++ b/media/java/android/media/tv/tuner/FilterSettings.java
@@ -40,6 +40,10 @@
     @FilterType
     public abstract int getType();
 
+    public Settings getSettings() {
+        return mSettings;
+    }
+
     // TODO: more builders and getters
 
     /**
diff --git a/media/java/android/media/tv/tuner/FrontendCapabilities.java b/media/java/android/media/tv/tuner/FrontendCapabilities.java
new file mode 100644
index 0000000..fcfd7c8
--- /dev/null
+++ b/media/java/android/media/tv/tuner/FrontendCapabilities.java
@@ -0,0 +1,291 @@
+/*
+ * 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.media.tv.tuner;
+
+/**
+ * Frontend Capabilities.
+ * @hide
+ */
+public class FrontendCapabilities {
+    /** Analog Capabilities. */
+    public class Analog extends FrontendCapabilities {
+        private final int mTypeCap;
+        private final int mSifStandardCap;
+
+        Analog(int typeCap, int sifStandardCap) {
+            mTypeCap = typeCap;
+            mSifStandardCap = sifStandardCap;
+        }
+        /**
+         * Gets type capability.
+         */
+        public int getTypeCapability() {
+            return mTypeCap;
+        }
+        /** Gets SIF standard capability. */
+        public int getSifStandardCapability() {
+            return mSifStandardCap;
+        }
+    }
+
+    /** ATSC Capabilities. */
+    public class Atsc extends FrontendCapabilities {
+        private final int mModulationCap;
+
+        Atsc(int modulationCap) {
+            mModulationCap = modulationCap;
+        }
+        /** Gets modulation capability. */
+        public int getModulationCapability() {
+            return mModulationCap;
+        }
+    }
+
+    /** ATSC-3 Capabilities. */
+    public class Atsc3 extends FrontendCapabilities {
+        private final int mBandwidthCap;
+        private final int mModulationCap;
+        private final int mTimeInterleaveModeCap;
+        private final int mCodeRateCap;
+        private final int mFecCap;
+        private final int mDemodOutputFormatCap;
+
+        Atsc3(int bandwidthCap, int modulationCap, int timeInterleaveModeCap, int codeRateCap,
+                int fecCap, int demodOutputFormatCap) {
+            mBandwidthCap = bandwidthCap;
+            mModulationCap = modulationCap;
+            mTimeInterleaveModeCap = timeInterleaveModeCap;
+            mCodeRateCap = codeRateCap;
+            mFecCap = fecCap;
+            mDemodOutputFormatCap = demodOutputFormatCap;
+        }
+
+        /** Gets bandwidth capability. */
+        public int getBandwidthCapability() {
+            return mBandwidthCap;
+        }
+        /** Gets modulation capability. */
+        public int getModulationCapability() {
+            return mModulationCap;
+        }
+        /** Gets time interleave mod capability. */
+        public int getTimeInterleaveModeCapability() {
+            return mTimeInterleaveModeCap;
+        }
+        /** Gets code rate capability. */
+        public int getCodeRateCapability() {
+            return mCodeRateCap;
+        }
+        /** Gets FEC capability. */
+        public int getFecCapability() {
+            return mFecCap;
+        }
+        /** Gets demodulator output format capability. */
+        public int getDemodOutputFormatCapability() {
+            return mDemodOutputFormatCap;
+        }
+    }
+
+    /** DVBS Capabilities. */
+    public class Dvbs extends FrontendCapabilities {
+        private final int mModulationCap;
+        private final long mInnerFecCap;
+        private final int mStandard;
+
+        Dvbs(int modulationCap, long innerFecCap, int standard) {
+            mModulationCap = modulationCap;
+            mInnerFecCap = innerFecCap;
+            mStandard = standard;
+        }
+
+        /** Gets modulation capability. */
+        public int getModulationCapability() {
+            return mModulationCap;
+        }
+        /** Gets inner FEC capability. */
+        public long getInnerFecCapability() {
+            return mInnerFecCap;
+        }
+        /** Gets DVBS standard capability. */
+        public int getStandardCapability() {
+            return mStandard;
+        }
+    }
+
+    /** DVBC Capabilities. */
+    public class Dvbc extends FrontendCapabilities {
+        private final int mModulationCap;
+        private final int mFecCap;
+        private final int mAnnexCap;
+
+        Dvbc(int modulationCap, int fecCap, int annexCap) {
+            mModulationCap = modulationCap;
+            mFecCap = fecCap;
+            mAnnexCap = annexCap;
+        }
+
+        /** Gets modulation capability. */
+        public int getModulationCapability() {
+            return mModulationCap;
+        }
+        /** Gets FEC capability. */
+        public int getFecCapability() {
+            return mFecCap;
+        }
+        /** Gets annex capability. */
+        public int getAnnexCapability() {
+            return mAnnexCap;
+        }
+    }
+
+    /** DVBT Capabilities. */
+    public class Dvbt extends FrontendCapabilities {
+        private final int mTransmissionModeCap;
+        private final int mBandwidthCap;
+        private final int mConstellationCap;
+        private final int mCoderateCap;
+        private final int mHierarchyCap;
+        private final int mGuardIntervalCap;
+        private final boolean mIsT2Supported;
+        private final boolean mIsMisoSupported;
+
+        Dvbt(int transmissionModeCap, int bandwidthCap, int constellationCap, int coderateCap,
+                int hierarchyCap, int guardIntervalCap, boolean isT2Supported,
+                boolean isMisoSupported) {
+            mTransmissionModeCap = transmissionModeCap;
+            mBandwidthCap = bandwidthCap;
+            mConstellationCap = constellationCap;
+            mCoderateCap = coderateCap;
+            mHierarchyCap = hierarchyCap;
+            mGuardIntervalCap = guardIntervalCap;
+            mIsT2Supported = isT2Supported;
+            mIsMisoSupported = isMisoSupported;
+        }
+
+        /** Gets transmission mode capability. */
+        public int getTransmissionModeCapability() {
+            return mTransmissionModeCap;
+        }
+        /** Gets bandwidth capability. */
+        public int getBandwidthCapability() {
+            return mBandwidthCap;
+        }
+        /** Gets constellation capability. */
+        public int getConstellationCapability() {
+            return mConstellationCap;
+        }
+        /** Gets code rate capability. */
+        public int getCodeRateCapability() {
+            return mCoderateCap;
+        }
+        /** Gets hierarchy capability. */
+        public int getHierarchyCapability() {
+            return mHierarchyCap;
+        }
+        /** Gets guard interval capability. */
+        public int getGuardIntervalCapability() {
+            return mGuardIntervalCap;
+        }
+        /** Returns whether T2 is supported. */
+        public boolean getIsT2Supported() {
+            return mIsT2Supported;
+        }
+        /** Returns whether MISO is supported. */
+        public boolean getIsMisoSupported() {
+            return mIsMisoSupported;
+        }
+    }
+
+    /** ISDBS Capabilities. */
+    public class Isdbs extends FrontendCapabilities {
+        private final int mModulationCap;
+        private final int mCoderateCap;
+
+        Isdbs(int modulationCap, int coderateCap) {
+            mModulationCap = modulationCap;
+            mCoderateCap = coderateCap;
+        }
+
+        /** Gets modulation capability. */
+        public int getModulationCapability() {
+            return mModulationCap;
+        }
+        /** Gets code rate capability. */
+        public int getCodeRateCapability() {
+            return mCoderateCap;
+        }
+    }
+
+    /** ISDBS-3 Capabilities. */
+    public class Isdbs3 extends FrontendCapabilities {
+        private final int mModulationCap;
+        private final int mCoderateCap;
+
+        Isdbs3(int modulationCap, int coderateCap) {
+            mModulationCap = modulationCap;
+            mCoderateCap = coderateCap;
+        }
+
+        /** Gets modulation capability. */
+        public int getModulationCapability() {
+            return mModulationCap;
+        }
+        /** Gets code rate capability. */
+        public int getCodeRateCapability() {
+            return mCoderateCap;
+        }
+    }
+
+    /** ISDBC Capabilities. */
+    public class Isdbc extends FrontendCapabilities {
+        private final int mModeCap;
+        private final int mBandwidthCap;
+        private final int mModulationCap;
+        private final int mCoderateCap;
+        private final int mGuardIntervalCap;
+
+        Isdbc(int modeCap, int bandwidthCap, int modulationCap, int coderateCap,
+                int guardIntervalCap) {
+            mModeCap = modeCap;
+            mBandwidthCap = bandwidthCap;
+            mModulationCap = modulationCap;
+            mCoderateCap = coderateCap;
+            mGuardIntervalCap = guardIntervalCap;
+        }
+
+        /** Gets mode capability. */
+        public int getModeCapability() {
+            return mModeCap;
+        }
+        /** Gets bandwidth capability. */
+        public int getBandwidthCapability() {
+            return mBandwidthCap;
+        }
+        /** Gets modulation capability. */
+        public int getModulationCapability() {
+            return mModulationCap;
+        }
+        /** Gets code rate capability. */
+        public int getCodeRateCapability() {
+            return mCoderateCap;
+        }
+        /** Gets guard interval capability. */
+        public int getGuardIntervalCapability() {
+            return mGuardIntervalCap;
+        }
+    }
+}
diff --git a/media/java/android/media/tv/tuner/FrontendInfo.java b/media/java/android/media/tv/tuner/FrontendInfo.java
new file mode 100644
index 0000000..2ab100d
--- /dev/null
+++ b/media/java/android/media/tv/tuner/FrontendInfo.java
@@ -0,0 +1,93 @@
+/*
+ * 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.media.tv.tuner;
+
+import android.media.tv.tuner.TunerConstants.FrontendType;
+
+/**
+ * Frontend info.
+ * @hide
+ */
+public class FrontendInfo {
+    private final int mId;
+    private final int mType;
+    private final int mMinFrequency;
+    private final int mMaxFrequency;
+    private final int mMinSymbolRate;
+    private final int mMaxSymbolRate;
+    private final int mAcquireRange;
+    private final int mExclusiveGroupId;
+    private final int[] mStatusCaps;
+    private final FrontendCapabilities mFrontendCap;
+
+    FrontendInfo(int id, int type, int minFrequency, int maxFrequency, int minSymbolRate,
+            int maxSymbolRate, int acquireRange, int exclusiveGroupId, int[] statusCaps,
+            FrontendCapabilities frontendCap) {
+        mId = id;
+        mType = type;
+        mMinFrequency = minFrequency;
+        mMaxFrequency = maxFrequency;
+        mMinSymbolRate = minSymbolRate;
+        mMaxSymbolRate = maxSymbolRate;
+        mAcquireRange = acquireRange;
+        mExclusiveGroupId = exclusiveGroupId;
+        mStatusCaps = statusCaps;
+        mFrontendCap = frontendCap;
+    }
+
+    /** Gets frontend ID. */
+    public int getId() {
+        return mId;
+    }
+    /** Gets frontend type. */
+    @FrontendType
+    public int getType() {
+        return mType;
+    }
+    /** Gets min frequency. */
+    public int getMinFrequency() {
+        return mMinFrequency;
+    }
+    /** Gets max frequency. */
+    public int getMaxFrequency() {
+        return mMaxFrequency;
+    }
+    /** Gets min symbol rate. */
+    public int getMinSymbolRate() {
+        return mMinSymbolRate;
+    }
+    /** Gets max symbol rate. */
+    public int getMaxSymbolRate() {
+        return mMaxSymbolRate;
+    }
+    /** Gets acquire range. */
+    public int getAcquireRange() {
+        return mAcquireRange;
+    }
+    /** Gets exclusive group ID. */
+    public int getExclusiveGroupId() {
+        return mExclusiveGroupId;
+    }
+    /** Gets status capabilities. */
+    public int[] getStatusCapabilities() {
+        return mStatusCaps;
+    }
+    /** Gets frontend capability. */
+    public FrontendCapabilities getFrontendCapability() {
+        return mFrontendCap;
+    }
+}
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index fcb03c0..63ef4b8 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -21,6 +21,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.content.Context;
+import android.media.tv.tuner.FilterSettings.Settings;
 import android.media.tv.tuner.TunerConstants.DemuxPidType;
 import android.media.tv.tuner.TunerConstants.FilterSubtype;
 import android.media.tv.tuner.TunerConstants.FilterType;
@@ -29,10 +30,12 @@
 import android.media.tv.tuner.TunerConstants.LnbTone;
 import android.media.tv.tuner.TunerConstants.LnbVoltage;
 import android.media.tv.tuner.TunerConstants.Result;
+import android.media.tv.tuner.filter.FilterEvent;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 
+import java.io.FileDescriptor;
 import java.util.List;
 
 /**
@@ -114,6 +117,7 @@
     private native long nativeGetAvSyncTime(int avSyncId);
     private native int nativeConnectCiCam(int ciCamId);
     private native int nativeDisconnectCiCam();
+    private native FrontendInfo nativeGetFrontendInfo(int id);
     private native Filter nativeOpenFilter(int type, int subType, int bufferSize);
 
     private native List<Integer> nativeGetLnbIds();
@@ -408,6 +412,28 @@
         return nativeDisconnectCiCam();
     }
 
+    /**
+     * Retrieve the frontend information.
+     * @hide
+     */
+    public FrontendInfo getFrontendInfo() {
+        if (mFrontend == null) {
+            throw new IllegalStateException("frontend is not initialized");
+        }
+        return nativeGetFrontendInfo(mFrontend.mId);
+    }
+
+    /**
+     * Gets frontend ID.
+     * @hide
+     */
+    public int getFrontendId() {
+        if (mFrontend == null) {
+            throw new IllegalStateException("frontend is not initialized");
+        }
+        return mFrontend.mId;
+    }
+
     private List<Integer> getFrontendIds() {
         mFrontendIds = nativeGetFrontendIds();
         return mFrontendIds;
@@ -464,8 +490,9 @@
          */
         public int configure(FilterSettings settings) {
             int subType = -1;
-            if (settings.mSettings != null) {
-                subType = settings.mSettings.getType();
+            Settings s = settings.getSettings();
+            if (s != null) {
+                subType = s.getType();
             }
             return nativeConfigureFilter(settings.getType(), subType, settings);
         }
@@ -765,6 +792,11 @@
         private native int nativeStopDvr();
         private native int nativeFlushDvr();
         private native int nativeClose();
+        private native void nativeSetFileDescriptor(FileDescriptor fd);
+        private native int nativeRead(int size);
+        private native int nativeRead(byte[] bytes, int offset, int size);
+        private native int nativeWrite(int size);
+        private native int nativeWrite(byte[] bytes, int offset, int size);
 
         private Dvr() {}
 
@@ -837,6 +869,45 @@
         public int close() {
             return nativeClose();
         }
+
+        /**
+         * Sets file descriptor to read/write data.
+         */
+        public void setFileDescriptor(FileDescriptor fd) {
+            nativeSetFileDescriptor(fd);
+        }
+
+        /**
+         * Reads data from the file for DVR playback.
+         */
+        public int read(int size) {
+            return nativeRead(size);
+        }
+
+        /**
+         * Reads data from the buffer for DVR playback.
+         */
+        public int read(@NonNull byte[] bytes, int offset, int size) {
+            if (size + offset > bytes.length) {
+                throw new ArrayIndexOutOfBoundsException(
+                        "Array length=" + bytes.length + ", offset=" + offset + ", size=" + size);
+            }
+            return nativeRead(bytes, offset, size);
+        }
+
+        /**
+         * Writes recording data to file.
+         */
+        public int write(int size) {
+            return nativeWrite(size);
+        }
+
+        /**
+         * Writes recording data to buffer.
+         */
+        public int write(@NonNull byte[] bytes, int offset, int size) {
+            return nativeWrite(bytes, offset, size);
+        }
     }
 
     private Dvr openDvr(int type, int bufferSize) {
diff --git a/media/java/android/media/tv/tuner/TunerConstants.java b/media/java/android/media/tv/tuner/TunerConstants.java
index e611431..e8e4b22 100644
--- a/media/java/android/media/tv/tuner/TunerConstants.java
+++ b/media/java/android/media/tv/tuner/TunerConstants.java
@@ -26,143 +26,207 @@
 /**
  * @hide
  */
-final class TunerConstants {
+public final class TunerConstants {
     public static final int INVALID_TS_PID = Constants.Constant.INVALID_TS_PID;
     public static final int INVALID_STREAM_ID = Constants.Constant.INVALID_STREAM_ID;
 
 
-    @Retention(RetentionPolicy.SOURCE)
+    /** @hide */
     @IntDef({FRONTEND_TYPE_UNDEFINED, FRONTEND_TYPE_ANALOG, FRONTEND_TYPE_ATSC, FRONTEND_TYPE_ATSC3,
             FRONTEND_TYPE_DVBC, FRONTEND_TYPE_DVBS, FRONTEND_TYPE_DVBT, FRONTEND_TYPE_ISDBS,
             FRONTEND_TYPE_ISDBS3, FRONTEND_TYPE_ISDBT})
+    @Retention(RetentionPolicy.SOURCE)
     public @interface FrontendType {}
 
+    /** @hide */
     public static final int FRONTEND_TYPE_UNDEFINED = Constants.FrontendType.UNDEFINED;
+    /** @hide */
     public static final int FRONTEND_TYPE_ANALOG = Constants.FrontendType.ANALOG;
+    /** @hide */
     public static final int FRONTEND_TYPE_ATSC = Constants.FrontendType.ATSC;
+    /** @hide */
     public static final int FRONTEND_TYPE_ATSC3 = Constants.FrontendType.ATSC3;
+    /** @hide */
     public static final int FRONTEND_TYPE_DVBC = Constants.FrontendType.DVBC;
+    /** @hide */
     public static final int FRONTEND_TYPE_DVBS = Constants.FrontendType.DVBS;
+    /** @hide */
     public static final int FRONTEND_TYPE_DVBT = Constants.FrontendType.DVBT;
+    /** @hide */
     public static final int FRONTEND_TYPE_ISDBS = Constants.FrontendType.ISDBS;
+    /** @hide */
     public static final int FRONTEND_TYPE_ISDBS3 = Constants.FrontendType.ISDBS3;
+    /** @hide */
     public static final int FRONTEND_TYPE_ISDBT = Constants.FrontendType.ISDBT;
 
 
-    @Retention(RetentionPolicy.SOURCE)
+    /** @hide */
     @IntDef({FRONTEND_EVENT_TYPE_LOCKED, FRONTEND_EVENT_TYPE_NO_SIGNAL,
             FRONTEND_EVENT_TYPE_LOST_LOCK})
+    @Retention(RetentionPolicy.SOURCE)
     public @interface FrontendEventType {}
-
+    /** @hide */
     public static final int FRONTEND_EVENT_TYPE_LOCKED = Constants.FrontendEventType.LOCKED;
+    /** @hide */
     public static final int FRONTEND_EVENT_TYPE_NO_SIGNAL = Constants.FrontendEventType.NO_SIGNAL;
+    /** @hide */
     public static final int FRONTEND_EVENT_TYPE_LOST_LOCK = Constants.FrontendEventType.LOST_LOCK;
 
 
-    @Retention(RetentionPolicy.SOURCE)
+    /** @hide */
     @IntDef({DATA_FORMAT_TS, DATA_FORMAT_PES, DATA_FORMAT_ES, DATA_FORMAT_SHV_TLV})
+    @Retention(RetentionPolicy.SOURCE)
     public @interface DataFormat {}
-
+    /** @hide */
     public static final int DATA_FORMAT_TS = Constants.DataFormat.TS;
+    /** @hide */
     public static final int DATA_FORMAT_PES = Constants.DataFormat.PES;
+    /** @hide */
     public static final int DATA_FORMAT_ES = Constants.DataFormat.ES;
+    /** @hide */
     public static final int DATA_FORMAT_SHV_TLV = Constants.DataFormat.SHV_TLV;
 
 
-    @Retention(RetentionPolicy.SOURCE)
+    /** @hide */
     @IntDef({DEMUX_T_PID, DEMUX_MMPT_PID})
+    @Retention(RetentionPolicy.SOURCE)
     public @interface DemuxPidType {}
-
+    /** @hide */
     public static final int DEMUX_T_PID = 1;
+    /** @hide */
     public static final int DEMUX_MMPT_PID = 2;
 
-    @Retention(RetentionPolicy.SOURCE)
+    /** @hide */
     @IntDef({FRONTEND_SETTINGS_ANALOG, FRONTEND_SETTINGS_ATSC, FRONTEND_SETTINGS_ATSC3,
             FRONTEND_SETTINGS_DVBS, FRONTEND_SETTINGS_DVBC, FRONTEND_SETTINGS_DVBT,
             FRONTEND_SETTINGS_ISDBS, FRONTEND_SETTINGS_ISDBS3, FRONTEND_SETTINGS_ISDBT})
+    @Retention(RetentionPolicy.SOURCE)
     public @interface FrontendSettingsType {}
-
+    /** @hide */
     public static final int FRONTEND_SETTINGS_ANALOG = 1;
+    /** @hide */
     public static final int FRONTEND_SETTINGS_ATSC = 2;
+    /** @hide */
     public static final int FRONTEND_SETTINGS_ATSC3 = 3;
+    /** @hide */
     public static final int FRONTEND_SETTINGS_DVBS = 4;
+    /** @hide */
     public static final int FRONTEND_SETTINGS_DVBC = 5;
+    /** @hide */
     public static final int FRONTEND_SETTINGS_DVBT = 6;
+    /** @hide */
     public static final int FRONTEND_SETTINGS_ISDBS = 7;
+    /** @hide */
     public static final int FRONTEND_SETTINGS_ISDBS3 = 8;
+    /** @hide */
     public static final int FRONTEND_SETTINGS_ISDBT = 9;
 
-    @Retention(RetentionPolicy.SOURCE)
+    /** @hide */
     @IntDef({FILTER_TYPE_TS, FILTER_TYPE_MMTP, FILTER_TYPE_IP, FILTER_TYPE_TLV, FILTER_TYPE_ALP})
+    @Retention(RetentionPolicy.SOURCE)
     public @interface FilterType {}
-
+    /** @hide */
     public static final int FILTER_TYPE_TS = Constants.DemuxFilterMainType.TS;
+    /** @hide */
     public static final int FILTER_TYPE_MMTP = Constants.DemuxFilterMainType.MMTP;
+    /** @hide */
     public static final int FILTER_TYPE_IP = Constants.DemuxFilterMainType.IP;
+    /** @hide */
     public static final int FILTER_TYPE_TLV = Constants.DemuxFilterMainType.TLV;
+    /** @hide */
     public static final int FILTER_TYPE_ALP = Constants.DemuxFilterMainType.ALP;
 
-    @Retention(RetentionPolicy.SOURCE)
+    /** @hide */
     @IntDef({FILTER_SUBTYPE_UNDEFINED, FILTER_SUBTYPE_SECTION, FILTER_SUBTYPE_PES,
             FILTER_SUBTYPE_AUDIO, FILTER_SUBTYPE_VIDEO, FILTER_SUBTYPE_DOWNLOAD,
             FILTER_SUBTYPE_RECORD, FILTER_SUBTYPE_TS, FILTER_SUBTYPE_PCR, FILTER_SUBTYPE_TEMI,
             FILTER_SUBTYPE_MMPT, FILTER_SUBTYPE_NTP, FILTER_SUBTYPE_IP_PAYLOAD, FILTER_SUBTYPE_IP,
             FILTER_SUBTYPE_PAYLOAD_THROUGH, FILTER_SUBTYPE_TLV, FILTER_SUBTYPE_PTP, })
+    @Retention(RetentionPolicy.SOURCE)
     public @interface FilterSubtype {}
-
+    /** @hide */
     public static final int FILTER_SUBTYPE_UNDEFINED = 0;
+    /** @hide */
     public static final int FILTER_SUBTYPE_SECTION = 1;
+    /** @hide */
     public static final int FILTER_SUBTYPE_PES = 2;
+    /** @hide */
     public static final int FILTER_SUBTYPE_AUDIO = 3;
+    /** @hide */
     public static final int FILTER_SUBTYPE_VIDEO = 4;
+    /** @hide */
     public static final int FILTER_SUBTYPE_DOWNLOAD = 5;
+    /** @hide */
     public static final int FILTER_SUBTYPE_RECORD = 6;
+    /** @hide */
     public static final int FILTER_SUBTYPE_TS = 7;
+    /** @hide */
     public static final int FILTER_SUBTYPE_PCR = 8;
+    /** @hide */
     public static final int FILTER_SUBTYPE_TEMI = 9;
+    /** @hide */
     public static final int FILTER_SUBTYPE_MMPT = 10;
+    /** @hide */
     public static final int FILTER_SUBTYPE_NTP = 11;
+    /** @hide */
     public static final int FILTER_SUBTYPE_IP_PAYLOAD = 12;
+    /** @hide */
     public static final int FILTER_SUBTYPE_IP = 13;
+    /** @hide */
     public static final int FILTER_SUBTYPE_PAYLOAD_THROUGH = 14;
+    /** @hide */
     public static final int FILTER_SUBTYPE_TLV = 15;
+    /** @hide */
     public static final int FILTER_SUBTYPE_PTP = 16;
 
-    @Retention(RetentionPolicy.SOURCE)
+    /** @hide */
     @IntDef({FRONTEND_SCAN_UNDEFINED, FRONTEND_SCAN_AUTO, FRONTEND_SCAN_BLIND})
+    @Retention(RetentionPolicy.SOURCE)
     public @interface FrontendScanType {}
-
+    /** @hide */
     public static final int FRONTEND_SCAN_UNDEFINED = Constants.FrontendScanType.SCAN_UNDEFINED;
+    /** @hide */
     public static final int FRONTEND_SCAN_AUTO = Constants.FrontendScanType.SCAN_AUTO;
+    /** @hide */
     public static final int FRONTEND_SCAN_BLIND = Constants.FrontendScanType.SCAN_BLIND;
 
-    @Retention(RetentionPolicy.SOURCE)
+    /** @hide */
     @IntDef({SCAN_MESSAGE_TYPE_LOCKED, SCAN_MESSAGE_TYPE_END, SCAN_MESSAGE_TYPE_PROGRESS_PERCENT,
             SCAN_MESSAGE_TYPE_FREQUENCY, SCAN_MESSAGE_TYPE_SYMBOL_RATE, SCAN_MESSAGE_TYPE_PLP_IDS,
             SCAN_MESSAGE_TYPE_GROUP_IDS, SCAN_MESSAGE_TYPE_INPUT_STREAM_IDS,
             SCAN_MESSAGE_TYPE_STANDARD, SCAN_MESSAGE_TYPE_ATSC3_PLP_INFO})
+    @Retention(RetentionPolicy.SOURCE)
     public @interface ScanMessageType {}
-
+    /** @hide */
     public static final int SCAN_MESSAGE_TYPE_LOCKED = Constants.FrontendScanMessageType.LOCKED;
+    /** @hide */
     public static final int SCAN_MESSAGE_TYPE_END = Constants.FrontendScanMessageType.END;
+    /** @hide */
     public static final int SCAN_MESSAGE_TYPE_PROGRESS_PERCENT =
             Constants.FrontendScanMessageType.PROGRESS_PERCENT;
+    /** @hide */
     public static final int SCAN_MESSAGE_TYPE_FREQUENCY =
             Constants.FrontendScanMessageType.FREQUENCY;
+    /** @hide */
     public static final int SCAN_MESSAGE_TYPE_SYMBOL_RATE =
             Constants.FrontendScanMessageType.SYMBOL_RATE;
+    /** @hide */
     public static final int SCAN_MESSAGE_TYPE_PLP_IDS = Constants.FrontendScanMessageType.PLP_IDS;
+    /** @hide */
     public static final int SCAN_MESSAGE_TYPE_GROUP_IDS =
             Constants.FrontendScanMessageType.GROUP_IDS;
+    /** @hide */
     public static final int SCAN_MESSAGE_TYPE_INPUT_STREAM_IDS =
             Constants.FrontendScanMessageType.INPUT_STREAM_IDS;
+    /** @hide */
     public static final int SCAN_MESSAGE_TYPE_STANDARD =
             Constants.FrontendScanMessageType.STANDARD;
+    /** @hide */
     public static final int SCAN_MESSAGE_TYPE_ATSC3_PLP_INFO =
             Constants.FrontendScanMessageType.ATSC3_PLP_INFO;
 
 
-    @Retention(RetentionPolicy.SOURCE)
+    /** @hide */
     @IntDef({FRONTEND_STATUS_TYPE_DEMOD_LOCK, FRONTEND_STATUS_TYPE_SNR, FRONTEND_STATUS_TYPE_BER,
             FRONTEND_STATUS_TYPE_PER, FRONTEND_STATUS_TYPE_PRE_BER,
             FRONTEND_STATUS_TYPE_SIGNAL_QUALITY, FRONTEND_STATUS_TYPE_SIGNAL_STRENGTH,
@@ -174,279 +238,342 @@
             FRONTEND_STATUS_TYPE_LBER_CN, FRONTEND_STATUS_TYPE_XER_CN, FRONTEND_STATUS_TYPE_MER,
             FRONTEND_STATUS_TYPE_FREQ_OFFSET, FRONTEND_STATUS_TYPE_HIERARCHY,
             FRONTEND_STATUS_TYPE_RF_LOCK, FRONTEND_STATUS_TYPE_ATSC3_PLP_INFO})
+    @Retention(RetentionPolicy.SOURCE)
     public @interface FrontendStatusType {}
 
     /**
      * Lock status for Demod.
+     * @hide
      */
     public static final int FRONTEND_STATUS_TYPE_DEMOD_LOCK =
             Constants.FrontendStatusType.DEMOD_LOCK;
     /**
      * Signal to Noise Ratio.
+     * @hide
      */
     public static final int FRONTEND_STATUS_TYPE_SNR = Constants.FrontendStatusType.SNR;
     /**
      * Bit Error Ratio.
+     * @hide
      */
     public static final int FRONTEND_STATUS_TYPE_BER = Constants.FrontendStatusType.BER;
     /**
      * Packages Error Ratio.
+     * @hide
      */
     public static final int FRONTEND_STATUS_TYPE_PER = Constants.FrontendStatusType.PER;
     /**
      * Bit Error Ratio before FEC.
+     * @hide
      */
     public static final int FRONTEND_STATUS_TYPE_PRE_BER = Constants.FrontendStatusType.PRE_BER;
     /**
      * Signal Quality (0..100). Good data over total data in percent can be
      * used as a way to present Signal Quality.
+     * @hide
      */
     public static final int FRONTEND_STATUS_TYPE_SIGNAL_QUALITY =
             Constants.FrontendStatusType.SIGNAL_QUALITY;
     /**
      * Signal Strength.
+     * @hide
      */
     public static final int FRONTEND_STATUS_TYPE_SIGNAL_STRENGTH =
             Constants.FrontendStatusType.SIGNAL_STRENGTH;
     /**
      * Symbol Rate.
+     * @hide
      */
     public static final int FRONTEND_STATUS_TYPE_SYMBOL_RATE =
             Constants.FrontendStatusType.SYMBOL_RATE;
     /**
      * Forward Error Correction Type.
+     * @hide
      */
     public static final int FRONTEND_STATUS_TYPE_FEC = Constants.FrontendStatusType.FEC;
     /**
      * Modulation Type.
+     * @hide
      */
     public static final int FRONTEND_STATUS_TYPE_MODULATION =
             Constants.FrontendStatusType.MODULATION;
     /**
      * Spectral Inversion Type.
+     * @hide
      */
     public static final int FRONTEND_STATUS_TYPE_SPECTRAL = Constants.FrontendStatusType.SPECTRAL;
     /**
      * LNB Voltage.
+     * @hide
      */
     public static final int FRONTEND_STATUS_TYPE_LNB_VOLTAGE =
             Constants.FrontendStatusType.LNB_VOLTAGE;
     /**
      * Physical Layer Pipe ID.
+     * @hide
      */
     public static final int FRONTEND_STATUS_TYPE_PLP_ID = Constants.FrontendStatusType.PLP_ID;
     /**
      * Status for Emergency Warning Broadcasting System.
+     * @hide
      */
     public static final int FRONTEND_STATUS_TYPE_EWBS = Constants.FrontendStatusType.EWBS;
     /**
      * Automatic Gain Control.
+     * @hide
      */
     public static final int FRONTEND_STATUS_TYPE_AGC = Constants.FrontendStatusType.AGC;
     /**
      * Low Noise Amplifier.
+     * @hide
      */
     public static final int FRONTEND_STATUS_TYPE_LNA = Constants.FrontendStatusType.LNA;
     /**
      * Error status by layer.
+     * @hide
      */
     public static final int FRONTEND_STATUS_TYPE_LAYER_ERROR =
             Constants.FrontendStatusType.LAYER_ERROR;
     /**
      * CN value by VBER.
+     * @hide
      */
     public static final int FRONTEND_STATUS_TYPE_VBER_CN = Constants.FrontendStatusType.VBER_CN;
     /**
      * CN value by LBER.
+     * @hide
      */
     public static final int FRONTEND_STATUS_TYPE_LBER_CN = Constants.FrontendStatusType.LBER_CN;
     /**
      * CN value by XER.
+     * @hide
      */
     public static final int FRONTEND_STATUS_TYPE_XER_CN = Constants.FrontendStatusType.XER_CN;
     /**
      * Moduration Error Ratio.
+     * @hide
      */
     public static final int FRONTEND_STATUS_TYPE_MER = Constants.FrontendStatusType.MER;
     /**
      * Difference between tuning frequency and actual locked frequency.
+     * @hide
      */
     public static final int FRONTEND_STATUS_TYPE_FREQ_OFFSET =
             Constants.FrontendStatusType.FREQ_OFFSET;
     /**
      * Hierarchy for DVBT.
+     * @hide
      */
     public static final int FRONTEND_STATUS_TYPE_HIERARCHY = Constants.FrontendStatusType.HIERARCHY;
     /**
      * Lock status for RF.
+     * @hide
      */
     public static final int FRONTEND_STATUS_TYPE_RF_LOCK = Constants.FrontendStatusType.RF_LOCK;
     /**
      * PLP information in a frequency band for ATSC3.0 frontend.
+     * @hide
      */
     public static final int FRONTEND_STATUS_TYPE_ATSC3_PLP_INFO =
             Constants.FrontendStatusType.ATSC3_PLP_INFO;
 
-
-    @Retention(RetentionPolicy.SOURCE)
+    /** @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;
 
 
-    @Retention(RetentionPolicy.SOURCE)
+    /** @hide */
     @IntDef({DVBC_MODULATION_UNDEFINED, DVBC_MODULATION_AUTO, DVBC_MODULATION_MOD_16QAM,
             DVBC_MODULATION_MOD_32QAM, DVBC_MODULATION_MOD_64QAM, DVBC_MODULATION_MOD_128QAM,
             DVBC_MODULATION_MOD_256QAM, DVBS_MODULATION_UNDEFINED, DVBS_MODULATION_AUTO,
@@ -461,166 +588,621 @@
             ISDBS3_MODULATION_MOD_32APSK, ISDBT_MODULATION_UNDEFINED, ISDBT_MODULATION_AUTO,
             ISDBT_MODULATION_MOD_DQPSK, ISDBT_MODULATION_MOD_QPSK, ISDBT_MODULATION_MOD_16QAM,
             ISDBT_MODULATION_MOD_64QAM})
+    @Retention(RetentionPolicy.SOURCE)
     public @interface FrontendModulation {}
-
+    /** @hide */
     public static final int DVBC_MODULATION_UNDEFINED = Constants.FrontendDvbcModulation.UNDEFINED;
+    /** @hide */
     public static final int DVBC_MODULATION_AUTO = Constants.FrontendDvbcModulation.AUTO;
+    /** @hide */
     public static final int DVBC_MODULATION_MOD_16QAM = Constants.FrontendDvbcModulation.MOD_16QAM;
+    /** @hide */
     public static final int DVBC_MODULATION_MOD_32QAM = Constants.FrontendDvbcModulation.MOD_32QAM;
+    /** @hide */
     public static final int DVBC_MODULATION_MOD_64QAM = Constants.FrontendDvbcModulation.MOD_64QAM;
+    /** @hide */
     public static final int DVBC_MODULATION_MOD_128QAM =
             Constants.FrontendDvbcModulation.MOD_128QAM;
+    /** @hide */
     public static final int DVBC_MODULATION_MOD_256QAM =
             Constants.FrontendDvbcModulation.MOD_256QAM;
+    /** @hide */
     public static final int DVBS_MODULATION_UNDEFINED = Constants.FrontendDvbsModulation.UNDEFINED;
+    /** @hide */
     public static final int DVBS_MODULATION_AUTO = Constants.FrontendDvbsModulation.AUTO;
+    /** @hide */
     public static final int DVBS_MODULATION_MOD_QPSK = Constants.FrontendDvbsModulation.MOD_QPSK;
+    /** @hide */
     public static final int DVBS_MODULATION_MOD_8PSK = Constants.FrontendDvbsModulation.MOD_8PSK;
+    /** @hide */
     public static final int DVBS_MODULATION_MOD_16QAM = Constants.FrontendDvbsModulation.MOD_16QAM;
+    /** @hide */
     public static final int DVBS_MODULATION_MOD_16PSK = Constants.FrontendDvbsModulation.MOD_16PSK;
+    /** @hide */
     public static final int DVBS_MODULATION_MOD_32PSK = Constants.FrontendDvbsModulation.MOD_32PSK;
+    /** @hide */
     public static final int DVBS_MODULATION_MOD_ACM = Constants.FrontendDvbsModulation.MOD_ACM;
+    /** @hide */
     public static final int DVBS_MODULATION_MOD_8APSK = Constants.FrontendDvbsModulation.MOD_8APSK;
+    /** @hide */
     public static final int DVBS_MODULATION_MOD_16APSK =
             Constants.FrontendDvbsModulation.MOD_16APSK;
+    /** @hide */
     public static final int DVBS_MODULATION_MOD_32APSK =
             Constants.FrontendDvbsModulation.MOD_32APSK;
+    /** @hide */
     public static final int DVBS_MODULATION_MOD_64APSK =
             Constants.FrontendDvbsModulation.MOD_64APSK;
+    /** @hide */
     public static final int DVBS_MODULATION_MOD_128APSK =
             Constants.FrontendDvbsModulation.MOD_128APSK;
+    /** @hide */
     public static final int DVBS_MODULATION_MOD_256APSK =
             Constants.FrontendDvbsModulation.MOD_256APSK;
+    /** @hide */
     public static final int DVBS_MODULATION_MOD_RESERVED =
             Constants.FrontendDvbsModulation.MOD_RESERVED;
+    /** @hide */
     public static final int ISDBS_MODULATION_UNDEFINED =
             Constants.FrontendIsdbsModulation.UNDEFINED;
+    /** @hide */
     public static final int ISDBS_MODULATION_AUTO = Constants.FrontendIsdbsModulation.AUTO;
+    /** @hide */
     public static final int ISDBS_MODULATION_MOD_BPSK = Constants.FrontendIsdbsModulation.MOD_BPSK;
+    /** @hide */
     public static final int ISDBS_MODULATION_MOD_QPSK = Constants.FrontendIsdbsModulation.MOD_QPSK;
+    /** @hide */
     public static final int ISDBS_MODULATION_MOD_TC8PSK =
             Constants.FrontendIsdbsModulation.MOD_TC8PSK;
+    /** @hide */
     public static final int ISDBS3_MODULATION_UNDEFINED =
             Constants.FrontendIsdbs3Modulation.UNDEFINED;
+    /** @hide */
     public static final int ISDBS3_MODULATION_AUTO = Constants.FrontendIsdbs3Modulation.AUTO;
+    /** @hide */
     public static final int ISDBS3_MODULATION_MOD_BPSK =
             Constants.FrontendIsdbs3Modulation.MOD_BPSK;
+    /** @hide */
     public static final int ISDBS3_MODULATION_MOD_QPSK =
             Constants.FrontendIsdbs3Modulation.MOD_QPSK;
+    /** @hide */
     public static final int ISDBS3_MODULATION_MOD_8PSK =
             Constants.FrontendIsdbs3Modulation.MOD_8PSK;
+    /** @hide */
     public static final int ISDBS3_MODULATION_MOD_16APSK =
             Constants.FrontendIsdbs3Modulation.MOD_16APSK;
+    /** @hide */
     public static final int ISDBS3_MODULATION_MOD_32APSK =
             Constants.FrontendIsdbs3Modulation.MOD_32APSK;
+    /** @hide */
     public static final int ISDBT_MODULATION_UNDEFINED =
             Constants.FrontendIsdbtModulation.UNDEFINED;
+    /** @hide */
     public static final int ISDBT_MODULATION_AUTO = Constants.FrontendIsdbtModulation.AUTO;
+    /** @hide */
     public static final int ISDBT_MODULATION_MOD_DQPSK =
             Constants.FrontendIsdbtModulation.MOD_DQPSK;
+    /** @hide */
     public static final int ISDBT_MODULATION_MOD_QPSK = Constants.FrontendIsdbtModulation.MOD_QPSK;
+    /** @hide */
     public static final int ISDBT_MODULATION_MOD_16QAM =
             Constants.FrontendIsdbtModulation.MOD_16QAM;
+    /** @hide */
     public static final int ISDBT_MODULATION_MOD_64QAM =
             Constants.FrontendIsdbtModulation.MOD_64QAM;
 
 
-    @Retention(RetentionPolicy.SOURCE)
+    /** @hide */
     @IntDef({SPECTRAL_INVERSION_UNDEFINED, SPECTRAL_INVERSION_NORMAL, SPECTRAL_INVERSION_INVERTED})
+    @Retention(RetentionPolicy.SOURCE)
     public @interface FrontendDvbcSpectralInversion {}
-
+    /** @hide */
     public static final int SPECTRAL_INVERSION_UNDEFINED =
             Constants.FrontendDvbcSpectralInversion.UNDEFINED;
+    /** @hide */
     public static final int SPECTRAL_INVERSION_NORMAL =
             Constants.FrontendDvbcSpectralInversion.NORMAL;
+    /** @hide */
     public static final int SPECTRAL_INVERSION_INVERTED =
             Constants.FrontendDvbcSpectralInversion.INVERTED;
 
 
-    @Retention(RetentionPolicy.SOURCE)
+    /** @hide */
     @IntDef({HIERARCHY_UNDEFINED, HIERARCHY_AUTO, HIERARCHY_NON_NATIVE, HIERARCHY_1_NATIVE,
             HIERARCHY_2_NATIVE, HIERARCHY_4_NATIVE, HIERARCHY_NON_INDEPTH, HIERARCHY_1_INDEPTH,
             HIERARCHY_2_INDEPTH, HIERARCHY_4_INDEPTH})
+    @Retention(RetentionPolicy.SOURCE)
     public @interface FrontendDvbtHierarchy {}
-
+    /** @hide */
     public static final int HIERARCHY_UNDEFINED = Constants.FrontendDvbtHierarchy.UNDEFINED;
+    /** @hide */
     public static final int HIERARCHY_AUTO = Constants.FrontendDvbtHierarchy.AUTO;
+    /** @hide */
     public static final int HIERARCHY_NON_NATIVE =
             Constants.FrontendDvbtHierarchy.HIERARCHY_NON_NATIVE;
+    /** @hide */
     public static final int HIERARCHY_1_NATIVE = Constants.FrontendDvbtHierarchy.HIERARCHY_1_NATIVE;
+    /** @hide */
     public static final int HIERARCHY_2_NATIVE = Constants.FrontendDvbtHierarchy.HIERARCHY_2_NATIVE;
+    /** @hide */
     public static final int HIERARCHY_4_NATIVE = Constants.FrontendDvbtHierarchy.HIERARCHY_4_NATIVE;
+    /** @hide */
     public static final int HIERARCHY_NON_INDEPTH =
             Constants.FrontendDvbtHierarchy.HIERARCHY_NON_INDEPTH;
+    /** @hide */
     public static final int HIERARCHY_1_INDEPTH =
             Constants.FrontendDvbtHierarchy.HIERARCHY_1_INDEPTH;
+    /** @hide */
     public static final int HIERARCHY_2_INDEPTH =
             Constants.FrontendDvbtHierarchy.HIERARCHY_2_INDEPTH;
+    /** @hide */
     public static final int HIERARCHY_4_INDEPTH =
             Constants.FrontendDvbtHierarchy.HIERARCHY_4_INDEPTH;
 
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({FRONTEND_ANALOG_TYPE_UNDEFINED, FRONTEND_ANALOG_TYPE_PAL, FRONTEND_ANALOG_TYPE_SECAM,
+            FRONTEND_ANALOG_TYPE_NTSC})
+    public @interface FrontendAnalogType {}
+
+    public static final int FRONTEND_ANALOG_TYPE_UNDEFINED = Constants.FrontendAnalogType.UNDEFINED;
+    public static final int FRONTEND_ANALOG_TYPE_PAL = Constants.FrontendAnalogType.PAL;
+    public static final int FRONTEND_ANALOG_TYPE_SECAM = Constants.FrontendAnalogType.SECAM;
+    public static final int FRONTEND_ANALOG_TYPE_NTSC = Constants.FrontendAnalogType.NTSC;
 
     @Retention(RetentionPolicy.SOURCE)
+    @IntDef({FRONTEND_ANALOG_SIF_UNDEFINED, FRONTEND_ANALOG_SIF_BG, FRONTEND_ANALOG_SIF_BG_A2,
+            FRONTEND_ANALOG_SIF_BG_NICAM, FRONTEND_ANALOG_SIF_I, FRONTEND_ANALOG_SIF_DK,
+            FRONTEND_ANALOG_SIF_DK1, FRONTEND_ANALOG_SIF_DK2, FRONTEND_ANALOG_SIF_DK3,
+            FRONTEND_ANALOG_SIF_DK_NICAM, FRONTEND_ANALOG_SIF_L, FRONTEND_ANALOG_SIF_M,
+            FRONTEND_ANALOG_SIF_M_BTSC, FRONTEND_ANALOG_SIF_M_A2, FRONTEND_ANALOG_SIF_M_EIA_J,
+            FRONTEND_ANALOG_SIF_I_NICAM, FRONTEND_ANALOG_SIF_L_NICAM, FRONTEND_ANALOG_SIF_L_PRIME})
+    public @interface FrontendAnalogSifStandard {}
+
+    public static final int FRONTEND_ANALOG_SIF_UNDEFINED =
+            Constants.FrontendAnalogSifStandard.UNDEFINED;
+    public static final int FRONTEND_ANALOG_SIF_BG = Constants.FrontendAnalogSifStandard.BG;
+    public static final int FRONTEND_ANALOG_SIF_BG_A2 = Constants.FrontendAnalogSifStandard.BG_A2;
+    public static final int FRONTEND_ANALOG_SIF_BG_NICAM =
+            Constants.FrontendAnalogSifStandard.BG_NICAM;
+    public static final int FRONTEND_ANALOG_SIF_I = Constants.FrontendAnalogSifStandard.I;
+    public static final int FRONTEND_ANALOG_SIF_DK = Constants.FrontendAnalogSifStandard.DK;
+    public static final int FRONTEND_ANALOG_SIF_DK1 = Constants.FrontendAnalogSifStandard.DK1;
+    public static final int FRONTEND_ANALOG_SIF_DK2 = Constants.FrontendAnalogSifStandard.DK2;
+    public static final int FRONTEND_ANALOG_SIF_DK3 = Constants.FrontendAnalogSifStandard.DK3;
+    public static final int FRONTEND_ANALOG_SIF_DK_NICAM =
+            Constants.FrontendAnalogSifStandard.DK_NICAM;
+    public static final int FRONTEND_ANALOG_SIF_L = Constants.FrontendAnalogSifStandard.L;
+    public static final int FRONTEND_ANALOG_SIF_M = Constants.FrontendAnalogSifStandard.M;
+    public static final int FRONTEND_ANALOG_SIF_M_BTSC = Constants.FrontendAnalogSifStandard.M_BTSC;
+    public static final int FRONTEND_ANALOG_SIF_M_A2 = Constants.FrontendAnalogSifStandard.M_A2;
+    public static final int FRONTEND_ANALOG_SIF_M_EIA_J =
+            Constants.FrontendAnalogSifStandard.M_EIA_J;
+    public static final int FRONTEND_ANALOG_SIF_I_NICAM =
+            Constants.FrontendAnalogSifStandard.I_NICAM;
+    public static final int FRONTEND_ANALOG_SIF_L_NICAM =
+            Constants.FrontendAnalogSifStandard.L_NICAM;
+    public static final int FRONTEND_ANALOG_SIF_L_PRIME =
+            Constants.FrontendAnalogSifStandard.L_PRIME;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({FRONTEND_ATSC_MODULATION_UNDEFINED, FRONTEND_ATSC_MODULATION_AUTO,
+            FRONTEND_ATSC_MODULATION_MOD_8VSB, FRONTEND_ATSC_MODULATION_MOD_16VSB})
+    public @interface FrontendAtscModulation {}
+
+    public static final int FRONTEND_ATSC_MODULATION_UNDEFINED =
+            Constants.FrontendAtscModulation.UNDEFINED;
+    public static final int FRONTEND_ATSC_MODULATION_AUTO = Constants.FrontendAtscModulation.AUTO;
+    public static final int FRONTEND_ATSC_MODULATION_MOD_8VSB =
+            Constants.FrontendAtscModulation.MOD_8VSB;
+    public static final int FRONTEND_ATSC_MODULATION_MOD_16VSB =
+            Constants.FrontendAtscModulation.MOD_16VSB;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({FRONTEND_ATSC3_BANDWIDTH_UNDEFINED, FRONTEND_ATSC3_BANDWIDTH_AUTO,
+            FRONTEND_ATSC3_BANDWIDTH_BANDWIDTH_6MHZ, FRONTEND_ATSC3_BANDWIDTH_BANDWIDTH_7MHZ,
+            FRONTEND_ATSC3_BANDWIDTH_BANDWIDTH_8MHZ})
+    public @interface FrontendAtsc3Bandwidth {}
+
+    public static final int FRONTEND_ATSC3_BANDWIDTH_UNDEFINED =
+            Constants.FrontendAtsc3Bandwidth.UNDEFINED;
+    public static final int FRONTEND_ATSC3_BANDWIDTH_AUTO = Constants.FrontendAtsc3Bandwidth.AUTO;
+    public static final int FRONTEND_ATSC3_BANDWIDTH_BANDWIDTH_6MHZ =
+            Constants.FrontendAtsc3Bandwidth.BANDWIDTH_6MHZ;
+    public static final int FRONTEND_ATSC3_BANDWIDTH_BANDWIDTH_7MHZ =
+            Constants.FrontendAtsc3Bandwidth.BANDWIDTH_7MHZ;
+    public static final int FRONTEND_ATSC3_BANDWIDTH_BANDWIDTH_8MHZ =
+            Constants.FrontendAtsc3Bandwidth.BANDWIDTH_8MHZ;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({FRONTEND_ATSC3_MODULATION_UNDEFINED, FRONTEND_ATSC3_MODULATION_AUTO,
+            FRONTEND_ATSC3_MODULATION_MOD_QPSK, FRONTEND_ATSC3_MODULATION_MOD_16QAM,
+            FRONTEND_ATSC3_MODULATION_MOD_64QAM, FRONTEND_ATSC3_MODULATION_MOD_256QAM,
+            FRONTEND_ATSC3_MODULATION_MOD_1024QAM, FRONTEND_ATSC3_MODULATION_MOD_4096QAM})
+    public @interface FrontendAtsc3Modulation {}
+
+    public static final int FRONTEND_ATSC3_MODULATION_UNDEFINED =
+            Constants.FrontendAtsc3Modulation.UNDEFINED;
+    public static final int FRONTEND_ATSC3_MODULATION_AUTO = Constants.FrontendAtsc3Modulation.AUTO;
+    public static final int FRONTEND_ATSC3_MODULATION_MOD_QPSK =
+            Constants.FrontendAtsc3Modulation.MOD_QPSK;
+    public static final int FRONTEND_ATSC3_MODULATION_MOD_16QAM =
+            Constants.FrontendAtsc3Modulation.MOD_16QAM;
+    public static final int FRONTEND_ATSC3_MODULATION_MOD_64QAM =
+            Constants.FrontendAtsc3Modulation.MOD_64QAM;
+    public static final int FRONTEND_ATSC3_MODULATION_MOD_256QAM =
+            Constants.FrontendAtsc3Modulation.MOD_256QAM;
+    public static final int FRONTEND_ATSC3_MODULATION_MOD_1024QAM =
+            Constants.FrontendAtsc3Modulation.MOD_1024QAM;
+    public static final int FRONTEND_ATSC3_MODULATION_MOD_4096QAM =
+            Constants.FrontendAtsc3Modulation.MOD_4096QAM;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({FRONTEND_ATSC3_TIME_INTERLEAVE_MODE_UNDEFINED,
+            FRONTEND_ATSC3_TIME_INTERLEAVE_MODE_AUTO, FRONTEND_ATSC3_TIME_INTERLEAVE_MODE_CTI,
+            FRONTEND_ATSC3_TIME_INTERLEAVE_MODE_HTI})
+    public @interface FrontendAtsc3TimeInterleaveMode {}
+
+    public static final int FRONTEND_ATSC3_TIME_INTERLEAVE_MODE_UNDEFINED =
+            Constants.FrontendAtsc3TimeInterleaveMode.UNDEFINED;
+    public static final int FRONTEND_ATSC3_TIME_INTERLEAVE_MODE_AUTO =
+            Constants.FrontendAtsc3TimeInterleaveMode.AUTO;
+    public static final int FRONTEND_ATSC3_TIME_INTERLEAVE_MODE_CTI =
+            Constants.FrontendAtsc3TimeInterleaveMode.CTI;
+    public static final int FRONTEND_ATSC3_TIME_INTERLEAVE_MODE_HTI =
+            Constants.FrontendAtsc3TimeInterleaveMode.HTI;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({FRONTEND_ATSC3_CODERATE_UNDEFINED, FRONTEND_ATSC3_CODERATE_AUTO,
+            FRONTEND_ATSC3_CODERATE_2_15, FRONTEND_ATSC3_CODERATE_3_15,
+            FRONTEND_ATSC3_CODERATE_4_15, FRONTEND_ATSC3_CODERATE_5_15,
+            FRONTEND_ATSC3_CODERATE_6_15, FRONTEND_ATSC3_CODERATE_7_15,
+            FRONTEND_ATSC3_CODERATE_8_15, FRONTEND_ATSC3_CODERATE_9_15,
+            FRONTEND_ATSC3_CODERATE_10_15, FRONTEND_ATSC3_CODERATE_11_15,
+            FRONTEND_ATSC3_CODERATE_12_15, FRONTEND_ATSC3_CODERATE_13_15})
+    public @interface FrontendAtsc3CodeRate {}
+
+    public static final int FRONTEND_ATSC3_CODERATE_UNDEFINED =
+            Constants.FrontendAtsc3CodeRate.UNDEFINED;
+    public static final int FRONTEND_ATSC3_CODERATE_AUTO = Constants.FrontendAtsc3CodeRate.AUTO;
+    public static final int FRONTEND_ATSC3_CODERATE_2_15 =
+            Constants.FrontendAtsc3CodeRate.CODERATE_2_15;
+    public static final int FRONTEND_ATSC3_CODERATE_3_15 =
+            Constants.FrontendAtsc3CodeRate.CODERATE_3_15;
+    public static final int FRONTEND_ATSC3_CODERATE_4_15 =
+            Constants.FrontendAtsc3CodeRate.CODERATE_4_15;
+    public static final int FRONTEND_ATSC3_CODERATE_5_15 =
+            Constants.FrontendAtsc3CodeRate.CODERATE_5_15;
+    public static final int FRONTEND_ATSC3_CODERATE_6_15 =
+            Constants.FrontendAtsc3CodeRate.CODERATE_6_15;
+    public static final int FRONTEND_ATSC3_CODERATE_7_15 =
+            Constants.FrontendAtsc3CodeRate.CODERATE_7_15;
+    public static final int FRONTEND_ATSC3_CODERATE_8_15 =
+            Constants.FrontendAtsc3CodeRate.CODERATE_8_15;
+    public static final int FRONTEND_ATSC3_CODERATE_9_15 =
+            Constants.FrontendAtsc3CodeRate.CODERATE_9_15;
+    public static final int FRONTEND_ATSC3_CODERATE_10_15 =
+            Constants.FrontendAtsc3CodeRate.CODERATE_10_15;
+    public static final int FRONTEND_ATSC3_CODERATE_11_15 =
+            Constants.FrontendAtsc3CodeRate.CODERATE_11_15;
+    public static final int FRONTEND_ATSC3_CODERATE_12_15 =
+            Constants.FrontendAtsc3CodeRate.CODERATE_12_15;
+    public static final int FRONTEND_ATSC3_CODERATE_13_15 =
+            Constants.FrontendAtsc3CodeRate.CODERATE_13_15;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({FRONTEND_ATSC3_FEC_UNDEFINED, FRONTEND_ATSC3_FEC_AUTO, FRONTEND_ATSC3_FEC_BCH_LDPC_16K,
+            FRONTEND_ATSC3_FEC_BCH_LDPC_64K, FRONTEND_ATSC3_FEC_CRC_LDPC_16K,
+            FRONTEND_ATSC3_FEC_CRC_LDPC_64K, FRONTEND_ATSC3_FEC_LDPC_16K,
+            FRONTEND_ATSC3_FEC_LDPC_64K})
+    public @interface FrontendAtsc3Fec {}
+
+    public static final int FRONTEND_ATSC3_FEC_UNDEFINED = Constants.FrontendAtsc3Fec.UNDEFINED;
+    public static final int FRONTEND_ATSC3_FEC_AUTO = Constants.FrontendAtsc3Fec.AUTO;
+    public static final int FRONTEND_ATSC3_FEC_BCH_LDPC_16K =
+            Constants.FrontendAtsc3Fec.BCH_LDPC_16K;
+    public static final int FRONTEND_ATSC3_FEC_BCH_LDPC_64K =
+            Constants.FrontendAtsc3Fec.BCH_LDPC_64K;
+    public static final int FRONTEND_ATSC3_FEC_CRC_LDPC_16K =
+            Constants.FrontendAtsc3Fec.CRC_LDPC_16K;
+    public static final int FRONTEND_ATSC3_FEC_CRC_LDPC_64K =
+            Constants.FrontendAtsc3Fec.CRC_LDPC_64K;
+    public static final int FRONTEND_ATSC3_FEC_LDPC_16K = Constants.FrontendAtsc3Fec.LDPC_16K;
+    public static final int FRONTEND_ATSC3_FEC_LDPC_64K = Constants.FrontendAtsc3Fec.LDPC_64K;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({FRONTEND_ATSC3_DEMOD_OUTPUT_FORMAT_UNDEFINED,
+            FRONTEND_ATSC3_DEMOD_OUTPUT_FORMAT_ATSC3_LINKLAYER_PACKET,
+            FRONTEND_ATSC3_DEMOD_OUTPUT_FORMAT_BASEBAND_PACKET})
+    public @interface FrontendAtsc3DemodOutputFormat {}
+
+    public static final int FRONTEND_ATSC3_DEMOD_OUTPUT_FORMAT_UNDEFINED =
+            Constants.FrontendAtsc3DemodOutputFormat.UNDEFINED;
+    public static final int FRONTEND_ATSC3_DEMOD_OUTPUT_FORMAT_ATSC3_LINKLAYER_PACKET =
+            Constants.FrontendAtsc3DemodOutputFormat.ATSC3_LINKLAYER_PACKET;
+    public static final int FRONTEND_ATSC3_DEMOD_OUTPUT_FORMAT_BASEBAND_PACKET =
+            Constants.FrontendAtsc3DemodOutputFormat.BASEBAND_PACKET;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({FRONTEND_DVBS_STANDARD_AUTO, FRONTEND_DVBS_STANDARD_S, FRONTEND_DVBS_STANDARD_S2,
+            FRONTEND_DVBS_STANDARD_S2X})
+    public @interface FrontendDvbsStandard {}
+
+    public static final int FRONTEND_DVBS_STANDARD_AUTO = Constants.FrontendDvbsStandard.AUTO;
+    public static final int FRONTEND_DVBS_STANDARD_S = Constants.FrontendDvbsStandard.S;
+    public static final int FRONTEND_DVBS_STANDARD_S2 = Constants.FrontendDvbsStandard.S2;
+    public static final int FRONTEND_DVBS_STANDARD_S2X = Constants.FrontendDvbsStandard.S2X;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({FRONTEND_DVBC_ANNEX_UNDEFINED, FRONTEND_DVBC_ANNEX_A, FRONTEND_DVBC_ANNEX_B,
+            FRONTEND_DVBC_ANNEX_C})
+    public @interface FrontendDvbcAnnex {}
+
+    public static final int FRONTEND_DVBC_ANNEX_UNDEFINED = Constants.FrontendDvbcAnnex.UNDEFINED;
+    public static final int FRONTEND_DVBC_ANNEX_A = Constants.FrontendDvbcAnnex.A;
+    public static final int FRONTEND_DVBC_ANNEX_B = Constants.FrontendDvbcAnnex.B;
+    public static final int FRONTEND_DVBC_ANNEX_C = Constants.FrontendDvbcAnnex.C;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({FRONTEND_DVBT_TRANSMISSION_MODE_UNDEFINED, FRONTEND_DVBT_TRANSMISSION_MODE_AUTO,
+            FRONTEND_DVBT_TRANSMISSION_MODE_2K, FRONTEND_DVBT_TRANSMISSION_MODE_8K,
+            FRONTEND_DVBT_TRANSMISSION_MODE_4K, FRONTEND_DVBT_TRANSMISSION_MODE_1K,
+            FRONTEND_DVBT_TRANSMISSION_MODE_16K, FRONTEND_DVBT_TRANSMISSION_MODE_32K})
+    public @interface FrontendDvbtTransmissionMode {}
+
+    public static final int FRONTEND_DVBT_TRANSMISSION_MODE_UNDEFINED =
+            Constants.FrontendDvbtTransmissionMode.UNDEFINED;
+    public static final int FRONTEND_DVBT_TRANSMISSION_MODE_AUTO =
+            Constants.FrontendDvbtTransmissionMode.AUTO;
+    public static final int FRONTEND_DVBT_TRANSMISSION_MODE_2K =
+            Constants.FrontendDvbtTransmissionMode.MODE_2K;
+    public static final int FRONTEND_DVBT_TRANSMISSION_MODE_8K =
+            Constants.FrontendDvbtTransmissionMode.MODE_8K;
+    public static final int FRONTEND_DVBT_TRANSMISSION_MODE_4K =
+            Constants.FrontendDvbtTransmissionMode.MODE_4K;
+    public static final int FRONTEND_DVBT_TRANSMISSION_MODE_1K =
+            Constants.FrontendDvbtTransmissionMode.MODE_1K;
+    public static final int FRONTEND_DVBT_TRANSMISSION_MODE_16K =
+            Constants.FrontendDvbtTransmissionMode.MODE_16K;
+    public static final int FRONTEND_DVBT_TRANSMISSION_MODE_32K =
+            Constants.FrontendDvbtTransmissionMode.MODE_32K;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({FRONTEND_DVBT_BANDWIDTH_UNDEFINED, FRONTEND_DVBT_BANDWIDTH_AUTO,
+            FRONTEND_DVBT_BANDWIDTH_8MHZ, FRONTEND_DVBT_BANDWIDTH_7MHZ,
+            FRONTEND_DVBT_BANDWIDTH_6MHZ, FRONTEND_DVBT_BANDWIDTH_5MHZ,
+            FRONTEND_DVBT_BANDWIDTH_1_7MHZ, FRONTEND_DVBT_BANDWIDTH_10MHZ})
+    public @interface FrontendDvbtBandwidth {}
+
+    public static final int FRONTEND_DVBT_BANDWIDTH_UNDEFINED =
+            Constants.FrontendDvbtBandwidth.UNDEFINED;
+    public static final int FRONTEND_DVBT_BANDWIDTH_AUTO = Constants.FrontendDvbtBandwidth.AUTO;
+    public static final int FRONTEND_DVBT_BANDWIDTH_8MHZ =
+            Constants.FrontendDvbtBandwidth.BANDWIDTH_8MHZ;
+    public static final int FRONTEND_DVBT_BANDWIDTH_7MHZ =
+            Constants.FrontendDvbtBandwidth.BANDWIDTH_7MHZ;
+    public static final int FRONTEND_DVBT_BANDWIDTH_6MHZ =
+            Constants.FrontendDvbtBandwidth.BANDWIDTH_6MHZ;
+    public static final int FRONTEND_DVBT_BANDWIDTH_5MHZ =
+            Constants.FrontendDvbtBandwidth.BANDWIDTH_5MHZ;
+    public static final int FRONTEND_DVBT_BANDWIDTH_1_7MHZ =
+            Constants.FrontendDvbtBandwidth.BANDWIDTH_1_7MHZ;
+    public static final int FRONTEND_DVBT_BANDWIDTH_10MHZ =
+            Constants.FrontendDvbtBandwidth.BANDWIDTH_10MHZ;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({FRONTEND_DVBT_CONSTELLATION_UNDEFINED, FRONTEND_DVBT_CONSTELLATION_AUTO,
+            FRONTEND_DVBT_CONSTELLATION_CONSTELLATION_QPSK,
+            FRONTEND_DVBT_CONSTELLATION_CONSTELLATION_16QAM,
+            FRONTEND_DVBT_CONSTELLATION_CONSTELLATION_64QAM,
+            FRONTEND_DVBT_CONSTELLATION_CONSTELLATION_256QAM})
+    public @interface FrontendDvbtConstellation {}
+
+    public static final int FRONTEND_DVBT_CONSTELLATION_UNDEFINED =
+            Constants.FrontendDvbtConstellation.UNDEFINED;
+    public static final int FRONTEND_DVBT_CONSTELLATION_AUTO =
+            Constants.FrontendDvbtConstellation.AUTO;
+    public static final int FRONTEND_DVBT_CONSTELLATION_CONSTELLATION_QPSK =
+            Constants.FrontendDvbtConstellation.CONSTELLATION_QPSK;
+    public static final int FRONTEND_DVBT_CONSTELLATION_CONSTELLATION_16QAM =
+            Constants.FrontendDvbtConstellation.CONSTELLATION_16QAM;
+    public static final int FRONTEND_DVBT_CONSTELLATION_CONSTELLATION_64QAM =
+            Constants.FrontendDvbtConstellation.CONSTELLATION_64QAM;
+    public static final int FRONTEND_DVBT_CONSTELLATION_CONSTELLATION_256QAM =
+            Constants.FrontendDvbtConstellation.CONSTELLATION_256QAM;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({FRONTEND_DVBT_CODERATE_UNDEFINED, FRONTEND_DVBT_CODERATE_AUTO,
+            FRONTEND_DVBT_CODERATE_1_2, FRONTEND_DVBT_CODERATE_2_3, FRONTEND_DVBT_CODERATE_3_4,
+            FRONTEND_DVBT_CODERATE_5_6, FRONTEND_DVBT_CODERATE_7_8, FRONTEND_DVBT_CODERATE_3_5,
+            FRONTEND_DVBT_CODERATE_4_5, FRONTEND_DVBT_CODERATE_6_7, FRONTEND_DVBT_CODERATE_8_9})
+    public @interface FrontendDvbtCoderate {}
+
+    public static final int FRONTEND_DVBT_CODERATE_UNDEFINED =
+            Constants.FrontendDvbtCoderate.UNDEFINED;
+    public static final int FRONTEND_DVBT_CODERATE_AUTO = Constants.FrontendDvbtCoderate.AUTO;
+    public static final int FRONTEND_DVBT_CODERATE_1_2 =
+            Constants.FrontendDvbtCoderate.CODERATE_1_2;
+    public static final int FRONTEND_DVBT_CODERATE_2_3 =
+            Constants.FrontendDvbtCoderate.CODERATE_2_3;
+    public static final int FRONTEND_DVBT_CODERATE_3_4 =
+            Constants.FrontendDvbtCoderate.CODERATE_3_4;
+    public static final int FRONTEND_DVBT_CODERATE_5_6 =
+            Constants.FrontendDvbtCoderate.CODERATE_5_6;
+    public static final int FRONTEND_DVBT_CODERATE_7_8 =
+            Constants.FrontendDvbtCoderate.CODERATE_7_8;
+    public static final int FRONTEND_DVBT_CODERATE_3_5 =
+            Constants.FrontendDvbtCoderate.CODERATE_3_5;
+    public static final int FRONTEND_DVBT_CODERATE_4_5 =
+            Constants.FrontendDvbtCoderate.CODERATE_4_5;
+    public static final int FRONTEND_DVBT_CODERATE_6_7 =
+            Constants.FrontendDvbtCoderate.CODERATE_6_7;
+    public static final int FRONTEND_DVBT_CODERATE_8_9 =
+            Constants.FrontendDvbtCoderate.CODERATE_8_9;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({FRONTEND_DVBT_GUARD_INTERVAL_UNDEFINED, FRONTEND_DVBT_GUARD_INTERVAL_AUTO,
+            FRONTEND_DVBT_GUARD_INTERVAL_INTERVAL_1_32, FRONTEND_DVBT_GUARD_INTERVAL_INTERVAL_1_16,
+            FRONTEND_DVBT_GUARD_INTERVAL_INTERVAL_1_8, FRONTEND_DVBT_GUARD_INTERVAL_INTERVAL_1_4,
+            FRONTEND_DVBT_GUARD_INTERVAL_INTERVAL_1_128,
+            FRONTEND_DVBT_GUARD_INTERVAL_INTERVAL_19_128,
+            FRONTEND_DVBT_GUARD_INTERVAL_INTERVAL_19_256})
+    public @interface FrontendDvbtGuardInterval {}
+
+    public static final int FRONTEND_DVBT_GUARD_INTERVAL_UNDEFINED =
+            Constants.FrontendDvbtGuardInterval.UNDEFINED;
+    public static final int FRONTEND_DVBT_GUARD_INTERVAL_AUTO =
+            Constants.FrontendDvbtGuardInterval.AUTO;
+    public static final int FRONTEND_DVBT_GUARD_INTERVAL_INTERVAL_1_32 =
+            Constants.FrontendDvbtGuardInterval.INTERVAL_1_32;
+    public static final int FRONTEND_DVBT_GUARD_INTERVAL_INTERVAL_1_16 =
+            Constants.FrontendDvbtGuardInterval.INTERVAL_1_16;
+    public static final int FRONTEND_DVBT_GUARD_INTERVAL_INTERVAL_1_8 =
+            Constants.FrontendDvbtGuardInterval.INTERVAL_1_8;
+    public static final int FRONTEND_DVBT_GUARD_INTERVAL_INTERVAL_1_4 =
+            Constants.FrontendDvbtGuardInterval.INTERVAL_1_4;
+    public static final int FRONTEND_DVBT_GUARD_INTERVAL_INTERVAL_1_128 =
+            Constants.FrontendDvbtGuardInterval.INTERVAL_1_128;
+    public static final int FRONTEND_DVBT_GUARD_INTERVAL_INTERVAL_19_128 =
+            Constants.FrontendDvbtGuardInterval.INTERVAL_19_128;
+    public static final int FRONTEND_DVBT_GUARD_INTERVAL_INTERVAL_19_256 =
+            Constants.FrontendDvbtGuardInterval.INTERVAL_19_256;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({FRONTEND_ISDBS_CODERATE_UNDEFINED, FRONTEND_ISDBS_CODERATE_AUTO,
+            FRONTEND_ISDBS_CODERATE_1_2, FRONTEND_ISDBS_CODERATE_2_3, FRONTEND_ISDBS_CODERATE_3_4,
+            FRONTEND_ISDBS_CODERATE_5_6, FRONTEND_ISDBS_CODERATE_7_8})
+    public @interface FrontendIsdbsCoderate {}
+
+    public static final int FRONTEND_ISDBS_CODERATE_UNDEFINED =
+            Constants.FrontendIsdbsCoderate.UNDEFINED;
+    public static final int FRONTEND_ISDBS_CODERATE_AUTO = Constants.FrontendIsdbsCoderate.AUTO;
+    public static final int FRONTEND_ISDBS_CODERATE_1_2 =
+            Constants.FrontendIsdbsCoderate.CODERATE_1_2;
+    public static final int FRONTEND_ISDBS_CODERATE_2_3 =
+            Constants.FrontendIsdbsCoderate.CODERATE_2_3;
+    public static final int FRONTEND_ISDBS_CODERATE_3_4 =
+            Constants.FrontendIsdbsCoderate.CODERATE_3_4;
+    public static final int FRONTEND_ISDBS_CODERATE_5_6 =
+            Constants.FrontendIsdbsCoderate.CODERATE_5_6;
+    public static final int FRONTEND_ISDBS_CODERATE_7_8 =
+            Constants.FrontendIsdbsCoderate.CODERATE_7_8;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({FRONTEND_ISDBT_MODE_UNDEFINED, FRONTEND_ISDBT_MODE_AUTO, FRONTEND_ISDBT_MODE_1,
+            FRONTEND_ISDBT_MODE_2, FRONTEND_ISDBT_MODE_3})
+    public @interface FrontendIsdbtMode {}
+
+    public static final int FRONTEND_ISDBT_MODE_UNDEFINED = Constants.FrontendIsdbtMode.UNDEFINED;
+    public static final int FRONTEND_ISDBT_MODE_AUTO = Constants.FrontendIsdbtMode.AUTO;
+    public static final int FRONTEND_ISDBT_MODE_1 = Constants.FrontendIsdbtMode.MODE_1;
+    public static final int FRONTEND_ISDBT_MODE_2 = Constants.FrontendIsdbtMode.MODE_2;
+    public static final int FRONTEND_ISDBT_MODE_3 = Constants.FrontendIsdbtMode.MODE_3;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({FRONTEND_ISDBT_BANDWIDTH_UNDEFINED, FRONTEND_ISDBT_BANDWIDTH_AUTO,
+            FRONTEND_ISDBT_BANDWIDTH_8MHZ, FRONTEND_ISDBT_BANDWIDTH_7MHZ,
+            FRONTEND_ISDBT_BANDWIDTH_6MHZ})
+    public @interface FrontendIsdbtBandwidth {}
+
+    public static final int FRONTEND_ISDBT_BANDWIDTH_UNDEFINED =
+            Constants.FrontendIsdbtBandwidth.UNDEFINED;
+    public static final int FRONTEND_ISDBT_BANDWIDTH_AUTO = Constants.FrontendIsdbtBandwidth.AUTO;
+    public static final int FRONTEND_ISDBT_BANDWIDTH_8MHZ =
+            Constants.FrontendIsdbtBandwidth.BANDWIDTH_8MHZ;
+    public static final int FRONTEND_ISDBT_BANDWIDTH_7MHZ =
+            Constants.FrontendIsdbtBandwidth.BANDWIDTH_7MHZ;
+    public static final int FRONTEND_ISDBT_BANDWIDTH_6MHZ =
+            Constants.FrontendIsdbtBandwidth.BANDWIDTH_6MHZ;
+
+    /** @hide */
     @IntDef({FILTER_SETTINGS_TS, FILTER_SETTINGS_MMTP, FILTER_SETTINGS_IP, FILTER_SETTINGS_TLV,
             FILTER_SETTINGS_ALP})
+    @Retention(RetentionPolicy.SOURCE)
     public @interface FilterSettingsType {}
-
+    /** @hide */
     public static final int FILTER_SETTINGS_TS = Constants.DemuxFilterMainType.TS;
+    /** @hide */
     public static final int FILTER_SETTINGS_MMTP = Constants.DemuxFilterMainType.MMTP;
+    /** @hide */
     public static final int FILTER_SETTINGS_IP = Constants.DemuxFilterMainType.IP;
+    /** @hide */
     public static final int FILTER_SETTINGS_TLV = Constants.DemuxFilterMainType.TLV;
+    /** @hide */
     public static final int FILTER_SETTINGS_ALP = Constants.DemuxFilterMainType.ALP;
 
-    @Retention(RetentionPolicy.SOURCE)
+    /** @hide */
     @IntDef({DVR_SETTINGS_RECORD, DVR_SETTINGS_PLAYBACK})
+    @Retention(RetentionPolicy.SOURCE)
     public @interface DvrSettingsType {}
-
+    /** @hide */
     public static final int DVR_SETTINGS_RECORD = Constants.DvrType.RECORD;
+    /** @hide */
     public static final int DVR_SETTINGS_PLAYBACK = Constants.DvrType.PLAYBACK;
 
 
-    @Retention(RetentionPolicy.SOURCE)
+    /** @hide */
     @IntDef({LNB_VOLTAGE_NONE, LNB_VOLTAGE_5V, LNB_VOLTAGE_11V, LNB_VOLTAGE_12V, LNB_VOLTAGE_13V,
             LNB_VOLTAGE_14V, LNB_VOLTAGE_15V, LNB_VOLTAGE_18V, LNB_VOLTAGE_19V})
+    @Retention(RetentionPolicy.SOURCE)
     public @interface LnbVoltage {}
-
+    /** @hide */
     public static final int LNB_VOLTAGE_NONE = Constants.LnbVoltage.NONE;
+    /** @hide */
     public static final int LNB_VOLTAGE_5V = Constants.LnbVoltage.VOLTAGE_5V;
+    /** @hide */
     public static final int LNB_VOLTAGE_11V = Constants.LnbVoltage.VOLTAGE_11V;
+    /** @hide */
     public static final int LNB_VOLTAGE_12V = Constants.LnbVoltage.VOLTAGE_12V;
+    /** @hide */
     public static final int LNB_VOLTAGE_13V = Constants.LnbVoltage.VOLTAGE_13V;
+    /** @hide */
     public static final int LNB_VOLTAGE_14V = Constants.LnbVoltage.VOLTAGE_14V;
+    /** @hide */
     public static final int LNB_VOLTAGE_15V = Constants.LnbVoltage.VOLTAGE_15V;
+    /** @hide */
     public static final int LNB_VOLTAGE_18V = Constants.LnbVoltage.VOLTAGE_18V;
+    /** @hide */
     public static final int LNB_VOLTAGE_19V = Constants.LnbVoltage.VOLTAGE_19V;
 
-    @Retention(RetentionPolicy.SOURCE)
+    /** @hide */
     @IntDef({LNB_TONE_NONE, LNB_TONE_CONTINUOUS})
+    @Retention(RetentionPolicy.SOURCE)
     public @interface LnbTone {}
-
+    /** @hide */
     public static final int LNB_TONE_NONE = Constants.LnbTone.NONE;
+    /** @hide */
     public static final int LNB_TONE_CONTINUOUS = Constants.LnbTone.CONTINUOUS;
 
-    @Retention(RetentionPolicy.SOURCE)
+    /** @hide */
     @IntDef({LNB_POSITION_UNDEFINED, LNB_POSITION_A, LNB_POSITION_B})
+    @Retention(RetentionPolicy.SOURCE)
     public @interface LnbPosition {}
-
+    /** @hide */
     public static final int LNB_POSITION_UNDEFINED = Constants.LnbPosition.UNDEFINED;
+    /** @hide */
     public static final int LNB_POSITION_A = Constants.LnbPosition.POSITION_A;
+    /** @hide */
     public static final int LNB_POSITION_B = Constants.LnbPosition.POSITION_B;
 
 
-    @Retention(RetentionPolicy.SOURCE)
+    /** @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)
     public @interface Result {}
-
+    /** @hide */
     public static final int RESULT_SUCCESS = Constants.Result.SUCCESS;
+    /** @hide */
     public static final int RESULT_UNAVAILABLE = Constants.Result.UNAVAILABLE;
+    /** @hide */
     public static final int RESULT_NOT_INITIALIZED = Constants.Result.NOT_INITIALIZED;
+    /** @hide */
     public static final int RESULT_INVALID_STATE = Constants.Result.INVALID_STATE;
+    /** @hide */
     public static final int RESULT_INVALID_ARGUMENT = Constants.Result.INVALID_ARGUMENT;
+    /** @hide */
     public static final int RESULT_OUT_OF_MEMORY = Constants.Result.OUT_OF_MEMORY;
+    /** @hide */
     public static final int RESULT_UNKNOWN_ERROR = Constants.Result.UNKNOWN_ERROR;
 
     private TunerConstants() {
diff --git a/media/java/android/media/tv/tuner/TunerUtils.java b/media/java/android/media/tv/tuner/TunerUtils.java
index b3bd780..a7ccb02 100644
--- a/media/java/android/media/tv/tuner/TunerUtils.java
+++ b/media/java/android/media/tv/tuner/TunerUtils.java
@@ -30,14 +30,26 @@
 public final class TunerUtils {
     private static final String PERMISSION = android.Manifest.permission.ACCESS_TV_TUNER;
 
-    static void checkTunerPermission(Context context) {
+    /**
+     * Checks whether the caller has permission to access tuner.
+     *
+     * @param context context of the caller.
+     * @throws SecurityException if the caller doesn't have the permission.
+     */
+    public static void checkTunerPermission(Context context) {
         if (context.checkCallingOrSelfPermission(PERMISSION)
                 != PackageManager.PERMISSION_GRANTED) {
             throw new SecurityException("Caller must have " + PERMISSION + " permission.");
         }
     }
 
-    static int getFilterSubtype(@FilterType int mainType, @FilterSubtype int subtype) {
+    /**
+     * Gets the corresponding filter subtype constant defined in tuner HAL.
+     *
+     * @param mainType filter main type.
+     * @param subtype filter subtype.
+     */
+    public static int getFilterSubtype(@FilterType int mainType, @FilterSubtype int subtype) {
         if (mainType == TunerConstants.FILTER_TYPE_TS) {
             switch (subtype) {
                 case TunerConstants.FILTER_SUBTYPE_UNDEFINED:
diff --git a/media/java/android/media/tv/tuner/filter/AudioExtraMetaData.java b/media/java/android/media/tv/tuner/filter/AudioExtraMetaData.java
new file mode 100644
index 0000000..306de84
--- /dev/null
+++ b/media/java/android/media/tv/tuner/filter/AudioExtraMetaData.java
@@ -0,0 +1,31 @@
+/*
+ * 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.media.tv.tuner.filter;
+
+/**
+ * Extra Meta Data from AD (Audio Descriptor) according to
+ * ETSI TS 101 154 V2.1.1.
+ * @hide
+ */
+public class AudioExtraMetaData {
+    private byte mAdFade;
+    private byte mAdPan;
+    private byte mVersionTextTag;
+    private byte mAdGainCenter;
+    private byte mAdGainFront;
+    private byte mAdGainSurround;
+}
diff --git a/media/java/android/media/tv/tuner/filter/DownloadEvent.java b/media/java/android/media/tv/tuner/filter/DownloadEvent.java
new file mode 100644
index 0000000..548fa77
--- /dev/null
+++ b/media/java/android/media/tv/tuner/filter/DownloadEvent.java
@@ -0,0 +1,30 @@
+/*
+ * 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.media.tv.tuner.filter;
+
+/**
+ * Download event.
+ * @hide
+ */
+public class DownloadEvent extends FilterEvent {
+    private int mItemId;
+    private int mMpuSequenceNumber;
+    private int mItemFragmentIndex;
+    private int mLastItemFragmentIndex;
+    private int mDataLength;
+}
+
diff --git a/media/java/android/media/tv/tuner/filter/FilterEvent.java b/media/java/android/media/tv/tuner/filter/FilterEvent.java
new file mode 100644
index 0000000..0a4fa86
--- /dev/null
+++ b/media/java/android/media/tv/tuner/filter/FilterEvent.java
@@ -0,0 +1,25 @@
+/*
+ * 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.media.tv.tuner.filter;
+
+/**
+ * Demux filter event.
+ *
+ * @hide
+ */
+public abstract class FilterEvent {
+}
diff --git a/media/java/android/media/tv/tuner/filter/IpPayloadEvent.java b/media/java/android/media/tv/tuner/filter/IpPayloadEvent.java
new file mode 100644
index 0000000..4da1d21
--- /dev/null
+++ b/media/java/android/media/tv/tuner/filter/IpPayloadEvent.java
@@ -0,0 +1,25 @@
+/*
+ * 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.media.tv.tuner.filter;
+
+/**
+ * IP payload event.
+ * @hide
+ */
+public class IpPayloadEvent extends FilterEvent {
+    private int mDataLength;
+}
diff --git a/media/java/android/media/tv/tuner/filter/MediaEvent.java b/media/java/android/media/tv/tuner/filter/MediaEvent.java
new file mode 100644
index 0000000..5e45350
--- /dev/null
+++ b/media/java/android/media/tv/tuner/filter/MediaEvent.java
@@ -0,0 +1,35 @@
+/*
+ * 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.media.tv.tuner.filter;
+
+import android.os.NativeHandle;
+
+/**
+ * Media event.
+ * @hide
+ */
+public class MediaEvent {
+    private int mStreamId;
+    private boolean mIsPtsPresent;
+    private long mPts;
+    private int mDataLength;
+    private NativeHandle mHandle;
+    private boolean mIsSecureMemory;
+    private int mMpuSequenceNumber;
+    private boolean mIsPrivateData;
+    private AudioExtraMetaData mExtraMetaData;
+}
diff --git a/media/java/android/media/tv/tuner/filter/MmtpRecordEvent.java b/media/java/android/media/tv/tuner/filter/MmtpRecordEvent.java
new file mode 100644
index 0000000..dbd8c77
--- /dev/null
+++ b/media/java/android/media/tv/tuner/filter/MmtpRecordEvent.java
@@ -0,0 +1,26 @@
+/*
+ * 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.media.tv.tuner.filter;
+
+/**
+ * MMPT record event.
+ * @hide
+ */
+public class MmtpRecordEvent extends FilterEvent {
+    private int mScHevcIndexMask;
+    private long mByteNumber;
+}
diff --git a/media/java/android/media/tv/tuner/filter/PesEvent.java b/media/java/android/media/tv/tuner/filter/PesEvent.java
new file mode 100644
index 0000000..16536e2
--- /dev/null
+++ b/media/java/android/media/tv/tuner/filter/PesEvent.java
@@ -0,0 +1,27 @@
+/*
+ * 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.media.tv.tuner.filter;
+
+/**
+ * PES event.
+ * @hide
+ */
+public class PesEvent extends FilterEvent {
+    private int mStreamId;
+    private int mDataLength;
+    private int mMpuSequenceNumber;
+}
diff --git a/media/java/android/media/tv/tuner/filter/SectionEvent.java b/media/java/android/media/tv/tuner/filter/SectionEvent.java
new file mode 100644
index 0000000..5b5f8c9
--- /dev/null
+++ b/media/java/android/media/tv/tuner/filter/SectionEvent.java
@@ -0,0 +1,29 @@
+/*
+ * 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.media.tv.tuner.filter;
+
+/**
+ * Section event.
+ * @hide
+ */
+public class SectionEvent {
+    // TODO: add constructor and getters
+    private int mTableId;
+    private int mVersion;
+    private int mSectionNum;
+    private int mDataLength;
+}
diff --git a/media/java/android/media/tv/tuner/filter/TemiEvent.java b/media/java/android/media/tv/tuner/filter/TemiEvent.java
new file mode 100644
index 0000000..3841604
--- /dev/null
+++ b/media/java/android/media/tv/tuner/filter/TemiEvent.java
@@ -0,0 +1,27 @@
+/*
+ * 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.media.tv.tuner.filter;
+
+/**
+ * TEMI event.
+ * @hide
+ */
+public class TemiEvent extends FilterEvent {
+    private long mPts;
+    private byte mDescrTag;
+    private byte[] mDescrData;
+}
diff --git a/media/java/android/media/tv/tuner/filter/TsRecordEvent.java b/media/java/android/media/tv/tuner/filter/TsRecordEvent.java
new file mode 100644
index 0000000..875b5bd
--- /dev/null
+++ b/media/java/android/media/tv/tuner/filter/TsRecordEvent.java
@@ -0,0 +1,27 @@
+/*
+ * 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.media.tv.tuner.filter;
+
+/**
+ * TS record event.
+ * @hide
+ */
+public class TsRecordEvent extends FilterEvent {
+    private int mTpid;
+    private int mIndexMask;
+    private long mByteNumber;
+}
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index 4ca23a1..ee67613 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -139,6 +139,7 @@
         "libfmq",
         "libhidlbase",
         "liblog",
+        "libnativehelper",
         "libutils",
     ],
 
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 9d2e855..3562782 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -22,6 +22,7 @@
 
 #include <android/hardware/tv/tuner/1.0/ITuner.h>
 #include <media/stagefright/foundation/ADebug.h>
+#include <nativehelper/JNIHelp.h>
 
 #pragma GCC diagnostic ignored "-Wunused-function"
 
@@ -92,7 +93,7 @@
 }
 
 void DvrCallback::setDvr(const jobject dvr) {
-    ALOGD("FilterCallback::setDvr");
+    ALOGD("DvrCallback::setDvr");
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     mDvr = env->NewWeakGlobalRef(dvr);
 }
@@ -101,10 +102,26 @@
 
 Dvr::Dvr(sp<IDvr> sp, jweak obj) : mDvrSp(sp), mDvrObj(obj) {}
 
+Dvr::~Dvr() {
+    EventFlag::deleteEventFlag(&mDvrMQEventFlag);
+}
+
+int Dvr::close() {
+    Result r = mDvrSp->close();
+    if (r == Result::SUCCESS) {
+        EventFlag::deleteEventFlag(&mDvrMQEventFlag);
+    }
+    return (int)r;
+}
+
 sp<IDvr> Dvr::getIDvr() {
     return mDvrSp;
 }
 
+DvrMQ& Dvr::getDvrMQ() {
+    return *mDvrMQ;
+}
+
 /////////////// FilterCallback ///////////////////////
 //TODO: implement filter callback
 Return<void> FilterCallback::onFilterEvent(const DemuxFilterEvent& /*filterEvent*/) {
@@ -652,6 +669,10 @@
     return 0;
 }
 
+static jobject android_media_tv_Tuner_get_frontend_info(JNIEnv*, jobject, jint) {
+    return NULL;
+}
+
 static jobject android_media_tv_Tuner_get_lnb_ids(JNIEnv *env, jobject thiz) {
     sp<JTuner> tuner = getTuner(env, thiz);
     return tuner->getLnbIds();
@@ -880,12 +901,28 @@
 }
 
 static int android_media_tv_Tuner_configure_dvr(JNIEnv *env, jobject dvr, jobject settings) {
-    sp<IDvr> dvrSp = getDvr(env, dvr)->getIDvr();
+    sp<Dvr> dvrSp = getDvr(env, dvr);
+    sp<IDvr> iDvrSp = dvrSp->getIDvr();
     if (dvrSp == NULL) {
         ALOGD("Failed to configure dvr: dvr not found");
         return (int)Result::INVALID_STATE;
     }
-    Result result = dvrSp->configure(getDvrSettings(env, settings));
+    Result result = iDvrSp->configure(getDvrSettings(env, settings));
+    MQDescriptorSync<uint8_t> dvrMQDesc;
+    if (result == Result::SUCCESS) {
+        Result getQueueDescResult = Result::UNKNOWN_ERROR;
+        iDvrSp->getQueueDesc(
+                [&](Result r, const MQDescriptorSync<uint8_t>& desc) {
+                    dvrMQDesc = desc;
+                    getQueueDescResult = r;
+                    ALOGD("getDvrQueueDesc");
+                });
+        if (getQueueDescResult == Result::SUCCESS) {
+            dvrSp->mDvrMQ = std::make_unique<DvrMQ>(dvrMQDesc, true);
+            EventFlag::createEventFlag(
+                    dvrSp->mDvrMQ->getEventFlagWord(), &(dvrSp->mDvrMQEventFlag));
+        }
+    }
     return (int)result;
 }
 
@@ -943,6 +980,115 @@
     return 0;
 }
 
+static void android_media_tv_Tuner_dvr_set_fd(JNIEnv *env, jobject dvr, jobject jfd) {
+    sp<Dvr> dvrSp = getDvr(env, dvr);
+    if (dvrSp == NULL) {
+        ALOGD("Failed to set FD for dvr: dvr not found");
+    }
+    dvrSp->mFd = jniGetFDFromFileDescriptor(env, jfd);
+    ALOGD("set fd = %d", dvrSp->mFd);
+}
+
+static int android_media_tv_Tuner_read_dvr(JNIEnv *env, jobject dvr, jint size) {
+    sp<Dvr> dvrSp = getDvr(env, dvr);
+    if (dvrSp == NULL) {
+        ALOGD("Failed to read dvr: dvr not found");
+    }
+
+    int available = dvrSp->mDvrMQ->availableToWrite();
+    int write = std::min(size, available);
+
+    DvrMQ::MemTransaction tx;
+    int ret = 0;
+    if (dvrSp->mDvrMQ->beginWrite(write, &tx)) {
+        auto first = tx.getFirstRegion();
+        auto data = first.getAddress();
+        int length = first.getLength();
+        int firstToWrite = std::min(length, write);
+        ret = read(dvrSp->mFd, data, firstToWrite);
+        if (ret < firstToWrite) {
+            ALOGW("[DVR] file to MQ, first region: %d bytes to write, but %d bytes written",
+                    firstToWrite, ret);
+        } else if (firstToWrite < write) {
+            ALOGD("[DVR] write second region: %d bytes written, %d bytes in total", ret, write);
+            auto second = tx.getSecondRegion();
+            data = second.getAddress();
+            length = second.getLength();
+            int secondToWrite = std::min(length, write - firstToWrite);
+            ret += read(dvrSp->mFd, data, secondToWrite);
+        }
+        ALOGD("[DVR] file to MQ: %d bytes need to be written, %d bytes written", write, ret);
+        if (!dvrSp->mDvrMQ->commitWrite(ret)) {
+            ALOGE("[DVR] Error: failed to commit write!");
+        }
+
+    } else {
+        ALOGE("dvrMq.beginWrite failed");
+    }
+    return ret;
+}
+
+static int android_media_tv_Tuner_read_dvr_from_array(
+        JNIEnv /* *env */, jobject /* dvr */, jbyteArray /* bytes */, jint /* offset */,
+        jint /* size */) {
+    //TODO: impl
+    return 0;
+}
+
+static int android_media_tv_Tuner_write_dvr(JNIEnv *env, jobject dvr, jint size) {
+    sp<Dvr> dvrSp = getDvr(env, dvr);
+    if (dvrSp == NULL) {
+        ALOGW("Failed to write dvr: dvr not found");
+        return 0;
+    }
+
+    if (dvrSp->mDvrMQ == NULL) {
+        ALOGW("Failed to write dvr: dvr not configured");
+        return 0;
+    }
+
+    DvrMQ& dvrMq = dvrSp->getDvrMQ();
+
+    int available = dvrMq.availableToRead();
+    int toRead = std::min(size, available);
+
+    int ret = 0;
+    DvrMQ::MemTransaction tx;
+    if (dvrMq.beginRead(toRead, &tx)) {
+        auto first = tx.getFirstRegion();
+        auto data = first.getAddress();
+        int length = first.getLength();
+        int firstToRead = std::min(length, toRead);
+        ret = write(dvrSp->mFd, data, firstToRead);
+        if (ret < firstToRead) {
+            ALOGW("[DVR] MQ to file: %d bytes read, but %d bytes written", firstToRead, ret);
+        } else if (firstToRead < toRead) {
+            ALOGD("[DVR] read second region: %d bytes read, %d bytes in total", ret, toRead);
+            auto second = tx.getSecondRegion();
+            data = second.getAddress();
+            length = second.getLength();
+            int secondToRead = toRead - firstToRead;
+            ret += write(dvrSp->mFd, data, secondToRead);
+        }
+        ALOGD("[DVR] MQ to file: %d bytes to be read, %d bytes written", toRead, ret);
+        if (!dvrMq.commitRead(ret)) {
+            ALOGE("[DVR] Error: failed to commit read!");
+        }
+
+    } else {
+        ALOGE("dvrMq.beginRead failed");
+    }
+
+    return ret;
+}
+
+static int android_media_tv_Tuner_write_dvr_to_array(
+        JNIEnv /* *env */, jobject /* dvr */, jbyteArray /* bytes */, jint /* offset */,
+        jint /* size */) {
+    //TODO: impl
+    return 0;
+}
+
 static const JNINativeMethod gTunerMethods[] = {
     { "nativeInit", "()V", (void *)android_media_tv_Tuner_native_init },
     { "nativeSetup", "()V", (void *)android_media_tv_Tuner_native_setup },
@@ -965,6 +1111,8 @@
     { "nativeGetAvSyncTime", "(I)J", (void *)android_media_tv_Tuner_gat_av_sync_time },
     { "nativeConnectCiCam", "(I)I", (void *)android_media_tv_Tuner_connect_cicam },
     { "nativeDisconnectCiCam", "()I", (void *)android_media_tv_Tuner_disconnect_cicam },
+    { "nativeGetFrontendInfo", "(I)[Landroid/media/tv/tuner/FrontendInfo;",
+            (void *)android_media_tv_Tuner_get_frontend_info },
     { "nativeOpenFilter", "(III)Landroid/media/tv/tuner/Tuner$Filter;",
             (void *)android_media_tv_Tuner_open_filter },
     { "nativeGetLnbIds", "()Ljava/util/List;",
@@ -1010,6 +1158,12 @@
     { "nativeStopDvr", "()I", (void *)android_media_tv_Tuner_stop_dvr },
     { "nativeFlushDvr", "()I", (void *)android_media_tv_Tuner_flush_dvr },
     { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_dvr },
+    { "nativeSetFileDescriptor", "(Ljava/io/FileDescriptor;)V",
+            (void *)android_media_tv_Tuner_dvr_set_fd },
+    { "nativeRead", "(I)I", (void *)android_media_tv_Tuner_read_dvr },
+    { "nativeRead", "([BII)I", (void *)android_media_tv_Tuner_read_dvr_from_array },
+    { "nativeWrite", "(I)I", (void *)android_media_tv_Tuner_write_dvr },
+    { "nativeWrite", "([BII)I", (void *)android_media_tv_Tuner_write_dvr_to_array },
 };
 
 static const JNINativeMethod gLnbMethods[] = {
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index d37a2d9..5c012bb 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -19,6 +19,8 @@
 
 #include <android/hardware/tv/tuner/1.0/ITuner.h>
 #include <fmq/MessageQueue.h>
+#include <fstream>
+#include <string>
 #include <unordered_map>
 #include <utils/RefBase.h>
 
@@ -58,6 +60,7 @@
 using ::android::hardware::tv::tuner::V1_0::RecordStatus;
 
 using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+using DvrMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
 
 namespace android {
 
@@ -80,9 +83,16 @@
 
 struct Dvr : public RefBase {
     Dvr(sp<IDvr> sp, jweak obj);
+    ~Dvr();
+    int close();
+    DvrMQ& getDvrMQ();
     sp<IDvr> getIDvr();
     sp<IDvr> mDvrSp;
     jweak mDvrObj;
+    std::unique_ptr<DvrMQ> mDvrMQ;
+    EventFlag* mDvrMQEventFlag;
+    std::string mFilePath;
+    int mFd;
 };
 
 struct FilterCallback : public IFilterCallback {
diff --git a/mms/java/android/telephony/MmsManager.java b/mms/java/android/telephony/MmsManager.java
index 4bcf046..6554267 100644
--- a/mms/java/android/telephony/MmsManager.java
+++ b/mms/java/android/telephony/MmsManager.java
@@ -97,22 +97,4 @@
             // Ignore it
         }
     }
-
-    /**
-     * Get carrier-dependent configuration values.
-     *
-     * @param subId the subscription id
-     * @return bundle key/values pairs of configuration values
-     */
-    public Bundle getCarrierConfigValues(int subId) {
-        try {
-            IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
-            if (iMms != null) {
-                return iMms.getCarrierConfigValues(subId);
-            }
-        } catch (RemoteException ex) {
-            // ignore it
-        }
-        return null;
-    }
 }
diff --git a/mms/java/com/android/internal/telephony/IMms.aidl b/mms/java/com/android/internal/telephony/IMms.aidl
index fa5073e..8be5111 100644
--- a/mms/java/com/android/internal/telephony/IMms.aidl
+++ b/mms/java/com/android/internal/telephony/IMms.aidl
@@ -60,13 +60,6 @@
             in PendingIntent downloadedIntent);
 
     /**
-     * Get carrier-dependent configuration values.
-     *
-     * @param subId the SIM id
-     */
-    Bundle getCarrierConfigValues(int subId);
-
-    /**
      * Import a text message into system's SMS store
      *
      * @param callingPkg the calling app's package name
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index b13c483..81739e0 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -1766,7 +1766,10 @@
         if (config.allowedKeyManagement.get(KeyMgmt.OWE)) {
             return SECURITY_OWE;
         }
-        return (config.wepKeys[0] != null) ? SECURITY_WEP : SECURITY_NONE;
+        return (config.wepTxKeyIndex >= 0
+                && config.wepTxKeyIndex < config.wepKeys.length
+                && config.wepKeys[config.wepTxKeyIndex] != null)
+                ? SECURITY_WEP : SECURITY_NONE;
     }
 
     public static String securityToString(int security, int pskType) {
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
index 3d414ee..0b5759b 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
@@ -633,8 +633,7 @@
         reportTetherStateChanged(mTetherStatesParcel);
 
         final Intent bcast = new Intent(ACTION_TETHER_STATE_CHANGED);
-        bcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
-                | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+        bcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
         bcast.putStringArrayListExtra(EXTRA_AVAILABLE_TETHER, availableList);
         bcast.putStringArrayListExtra(EXTRA_ACTIVE_LOCAL_ONLY, localOnlyList);
         bcast.putStringArrayListExtra(EXTRA_ACTIVE_TETHER, tetherList);
diff --git a/services/TEST_MAPPING b/services/TEST_MAPPING
new file mode 100644
index 0000000..5652ab1
--- /dev/null
+++ b/services/TEST_MAPPING
@@ -0,0 +1,48 @@
+{
+  "presubmit": [
+    {
+      "name": "FrameworksCoreTests",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        }
+      ]
+    },
+    {
+      "name": "FrameworksServicesTests",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        }
+      ]
+    },
+    {
+      "name": "FrameworksMockingCoreTests",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        }
+      ]
+    },
+    {
+      "name": "WmTests",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        }
+      ]
+    }
+  ]
+}
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 5b98f06..8d22300 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -94,8 +94,8 @@
         "android.hardware.light-V2.0-java",
         "android.hardware.power-V1.0-java",
         "android.hardware.tv.cec-V1.0-java",
+        "android.hardware.vibrator-java",
         "app-compat-annotations",
-        "vintf-vibrator-java",
         "framework-tethering",
     ],
 
diff --git a/services/core/java/com/android/server/MmsServiceBroker.java b/services/core/java/com/android/server/MmsServiceBroker.java
index 92d1da5..9b1326b 100644
--- a/services/core/java/com/android/server/MmsServiceBroker.java
+++ b/services/core/java/com/android/server/MmsServiceBroker.java
@@ -140,11 +140,6 @@
         }
 
         @Override
-        public Bundle getCarrierConfigValues(int subId) throws RemoteException {
-            return null;
-        }
-
-        @Override
         public Uri importTextMessage(String callingPkg, String address, int type, String text,
                 long timestampMillis, boolean seen, boolean read) throws RemoteException {
             return null;
@@ -373,12 +368,6 @@
         }
 
         @Override
-        public Bundle getCarrierConfigValues(int subId) throws RemoteException {
-            Slog.d(TAG, "getCarrierConfigValues() by " + getCallingPackageName());
-            return getServiceGuarded().getCarrierConfigValues(subId);
-        }
-
-        @Override
         public Uri importTextMessage(String callingPkg, String address, int type, String text,
                 long timestampMillis, boolean seen, boolean read) throws RemoteException {
             if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 5c418b0..8f99c1c 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -49,6 +49,13 @@
 import android.telephony.CellIdentity;
 import android.telephony.CellInfo;
 import android.telephony.CellLocation;
+import android.telephony.CellSignalStrength;
+import android.telephony.CellSignalStrengthCdma;
+import android.telephony.CellSignalStrengthGsm;
+import android.telephony.CellSignalStrengthLte;
+import android.telephony.CellSignalStrengthNr;
+import android.telephony.CellSignalStrengthTdscdma;
+import android.telephony.CellSignalStrengthWcdma;
 import android.telephony.DataFailCause;
 import android.telephony.DisconnectCause;
 import android.telephony.LocationAccessPolicy;
@@ -402,7 +409,11 @@
         mVoiceActivationState = copyOf(mVoiceActivationState, mNumPhones);
         mDataActivationState = copyOf(mDataActivationState, mNumPhones);
         mUserMobileDataState = copyOf(mUserMobileDataState, mNumPhones);
-        mSignalStrength = copyOf(mSignalStrength, mNumPhones);
+        if (mSignalStrength != null) {
+            mSignalStrength = copyOf(mSignalStrength, mNumPhones);
+        } else {
+            mSignalStrength = new SignalStrength[mNumPhones];
+        }
         mMessageWaiting = copyOf(mMessageWaiting, mNumPhones);
         mCallForwarding = copyOf(mCallForwarding, mNumPhones);
         mCellIdentity = copyOf(mCellIdentity, mNumPhones);
@@ -436,7 +447,7 @@
             mDataActivationState[i] = TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
             mCallIncomingNumber[i] =  "";
             mServiceState[i] =  new ServiceState();
-            mSignalStrength[i] =  new SignalStrength();
+            mSignalStrength[i] =  null;
             mUserMobileDataState[i] = false;
             mMessageWaiting[i] =  false;
             mCallForwarding[i] =  false;
@@ -520,7 +531,7 @@
             mDataActivationState[i] = TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
             mCallIncomingNumber[i] =  "";
             mServiceState[i] =  new ServiceState();
-            mSignalStrength[i] =  new SignalStrength();
+            mSignalStrength[i] =  null;
             mUserMobileDataState[i] = false;
             mMessageWaiting[i] =  false;
             mCallForwarding[i] =  false;
@@ -797,10 +808,12 @@
                     }
                     if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
                         try {
-                            int gsmSignalStrength = mSignalStrength[phoneId]
-                                    .getGsmSignalStrength();
-                            r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
-                                    : gsmSignalStrength));
+                            if (mSignalStrength[phoneId] != null) {
+                                int gsmSignalStrength = mSignalStrength[phoneId]
+                                        .getGsmSignalStrength();
+                                r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
+                                        : gsmSignalStrength));
+                            }
                         } catch (RemoteException ex) {
                             remove(r.binder);
                         }
@@ -857,7 +870,9 @@
                     }
                     if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
                         try {
-                            r.callback.onSignalStrengthsChanged(mSignalStrength[phoneId]);
+                            if (mSignalStrength[phoneId] != null) {
+                                r.callback.onSignalStrengthsChanged(mSignalStrength[phoneId]);
+                            }
                         } catch (RemoteException ex) {
                             remove(r.binder);
                         }
@@ -2168,13 +2183,32 @@
 
         Intent intent = new Intent(TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED);
         Bundle data = new Bundle();
-        signalStrength.fillInNotifierBundle(data);
+        fillInSignalStrengthNotifierBundle(signalStrength, data);
         intent.putExtras(data);
         intent.putExtra(PHONE_CONSTANTS_SUBSCRIPTION_KEY, subId);
         intent.putExtra(PHONE_CONSTANTS_SLOT_KEY, phoneId);
         mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
+    private void fillInSignalStrengthNotifierBundle(SignalStrength signalStrength, Bundle bundle) {
+        List<CellSignalStrength> cellSignalStrengths = signalStrength.getCellSignalStrengths();
+        for (CellSignalStrength cellSignalStrength : cellSignalStrengths) {
+            if (cellSignalStrength instanceof CellSignalStrengthLte) {
+                bundle.putParcelable("Lte", (CellSignalStrengthLte) cellSignalStrength);
+            } else if (cellSignalStrength instanceof CellSignalStrengthCdma) {
+                bundle.putParcelable("Cdma", (CellSignalStrengthCdma) cellSignalStrength);
+            } else if (cellSignalStrength instanceof CellSignalStrengthGsm) {
+                bundle.putParcelable("Gsm", (CellSignalStrengthGsm) cellSignalStrength);
+            } else if (cellSignalStrength instanceof CellSignalStrengthWcdma) {
+                bundle.putParcelable("Wcdma", (CellSignalStrengthWcdma) cellSignalStrength);
+            } else if (cellSignalStrength instanceof CellSignalStrengthTdscdma) {
+                bundle.putParcelable("Tdscdma", (CellSignalStrengthTdscdma) cellSignalStrength);
+            } else if (cellSignalStrength instanceof CellSignalStrengthNr) {
+                bundle.putParcelable("Nr", (CellSignalStrengthNr) cellSignalStrength);
+            }
+        }
+    }
+
     /**
      * Broadcasts an intent notifying apps of a phone state change. {@code subId} can be
      * a valid subId, in which case this function fires a subId-specific intent, or it
@@ -2483,11 +2517,14 @@
 
         if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
             try {
-                SignalStrength signalStrength = mSignalStrength[phoneId];
-                if (DBG) {
-                    log("checkPossibleMissNotify: onSignalStrengthsChanged SS=" + signalStrength);
+                if (mSignalStrength[phoneId] != null) {
+                    SignalStrength signalStrength = mSignalStrength[phoneId];
+                    if (DBG) {
+                        log("checkPossibleMissNotify: onSignalStrengthsChanged SS="
+                                + signalStrength);
+                    }
+                    r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength));
                 }
-                r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength));
             } catch (RemoteException ex) {
                 mRemoveList.add(r.binder);
             }
@@ -2495,14 +2532,16 @@
 
         if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
             try {
-                int gsmSignalStrength = mSignalStrength[phoneId]
-                        .getGsmSignalStrength();
-                if (DBG) {
-                    log("checkPossibleMissNotify: onSignalStrengthChanged SS=" +
-                            gsmSignalStrength);
+                if (mSignalStrength[phoneId] != null) {
+                    int gsmSignalStrength = mSignalStrength[phoneId]
+                            .getGsmSignalStrength();
+                    if (DBG) {
+                        log("checkPossibleMissNotify: onSignalStrengthChanged SS="
+                                + gsmSignalStrength);
+                    }
+                    r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
+                            : gsmSignalStrength));
                 }
-                r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
-                        : gsmSignalStrength));
             } catch (RemoteException ex) {
                 mRemoveList.add(r.binder);
             }
diff --git a/services/core/java/com/android/server/am/ActiveInstrumentation.java b/services/core/java/com/android/server/am/ActiveInstrumentation.java
index b2c82f0..db63638 100644
--- a/services/core/java/com/android/server/am/ActiveInstrumentation.java
+++ b/services/core/java/com/android/server/am/ActiveInstrumentation.java
@@ -67,6 +67,9 @@
     // Set to true when we have told the watcher the instrumentation is finished.
     boolean mFinished;
 
+    // The uid of the process who started this instrumentation.
+    int mSourceUid;
+
     ActiveInstrumentation(ActivityManagerService service) {
         mService = service;
     }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index a8b9562..4bc0297 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4341,6 +4341,18 @@
         final boolean allUids = mAtmInternal.isGetTasksAllowed(
                 "getProcessMemoryInfo", callingPid, callingUid);
 
+        // Check if the caller is actually instrumented and from shell, if it's true, we may lift
+        // the throttle of PSS info sampling.
+        boolean isCallerInstrumentedFromShell = false;
+        synchronized (mPidsSelfLocked) {
+            ProcessRecord caller = mPidsSelfLocked.get(callingPid);
+            if (caller != null) {
+                final ActiveInstrumentation instr = caller.getActiveInstrumentation();
+                isCallerInstrumentedFromShell = instr != null
+                        && (instr.mSourceUid == SHELL_UID || instr.mSourceUid == ROOT_UID);
+            }
+        }
+
         Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
         for (int i=pids.length-1; i>=0; i--) {
             infos[i] = new Debug.MemoryInfo();
@@ -4364,7 +4376,8 @@
                     continue; // Not allowed to see other users.
                 }
             }
-            if (proc != null && proc.lastMemInfoTime >= lastNow && proc.lastMemInfo != null) {
+            if (proc != null && proc.lastMemInfoTime >= lastNow && proc.lastMemInfo != null
+                    && !isCallerInstrumentedFromShell) {
                 // It hasn't been long enough that we want to take another sample; return
                 // the last one.
                 infos[i].set(proc.lastMemInfo);
@@ -16212,6 +16225,7 @@
                     disableTestApiChecks, mountExtStorageFull, abiOverride);
             app.setActiveInstrumentation(activeInstr);
             activeInstr.mFinished = false;
+            activeInstr.mSourceUid = callingUid;
             activeInstr.mRunningProcesses.add(app);
             if (!mActiveInstrumentation.contains(activeInstr)) {
                 mActiveInstrumentation.add(activeInstr);
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index ae3f368..e29d1a7 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -17,8 +17,10 @@
 package com.android.server.rollback;
 
 import android.Manifest;
+import android.annotation.AnyThread;
 import android.annotation.NonNull;
 import android.annotation.UserIdInt;
+import android.annotation.WorkerThread;
 import android.app.AppOpsManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -81,6 +83,11 @@
 
 /**
  * Implementation of service that manages APK level rollbacks.
+ *
+ * Threading model:
+ *
+ * - @AnyThread annotates thread-safe methods.
+ * - @WorkerThread annotates methods that should be called from the handler thread only.
  */
 class RollbackManagerServiceImpl extends IRollbackManager.Stub {
 
@@ -256,6 +263,7 @@
         registerTimeChangeReceiver();
     }
 
+    @AnyThread
     private void registerUserCallbacks(UserHandle user) {
         Context context = getContextAsUser(user);
         if (context == null) {
@@ -338,6 +346,7 @@
                     callerPackageName, statusReceiver));
     }
 
+    @AnyThread
     private void registerTimeChangeReceiver() {
         final BroadcastReceiver timeChangeIntentReceiver = new BroadcastReceiver() {
             @Override
@@ -362,6 +371,7 @@
                 null /* broadcastPermission */, getHandler());
     }
 
+    @AnyThread
     private static long calculateRelativeBootTime() {
         return System.currentTimeMillis() - SystemClock.elapsedRealtime();
     }
@@ -371,6 +381,7 @@
      * The work is done on the current thread. This may be a long running
      * operation.
      */
+    @WorkerThread
     private void commitRollbackInternal(int rollbackId, List<VersionedPackage> causePackages,
             String callerPackageName, IntentSender statusReceiver) {
         Slog.i(TAG, "commitRollback id=" + rollbackId + " caller=" + callerPackageName);
@@ -440,6 +451,7 @@
         });
     }
 
+    @WorkerThread
     private void queueSleepIfNeeded() {
         if (mSleepDuration.size() == 0) {
             return;
@@ -486,6 +498,7 @@
         }
     }
 
+    @WorkerThread
     private void updateRollbackLifetimeDurationInMillis() {
         mRollbackLifetimeDurationInMillis = DeviceConfig.getLong(
                 DeviceConfig.NAMESPACE_ROLLBACK_BOOT,
@@ -496,6 +509,7 @@
         }
     }
 
+    @AnyThread
     void onBootCompleted() {
         getHandler().post(() -> updateRollbackLifetimeDurationInMillis());
         // Also posts to handler thread
@@ -564,6 +578,7 @@
      * Removes all backups for the package not matching the currently
      * installed package version.
      */
+    @WorkerThread
     private void onPackageReplaced(String packageName) {
         // TODO: Could this end up incorrectly deleting a rollback for a
         // package that is about to be installed?
@@ -588,6 +603,7 @@
      * Called when a package has been completely removed from the device.
      * Removes all backups and rollback history for the given package.
      */
+    @WorkerThread
     private void onPackageFullyRemoved(String packageName) {
         expireRollbackForPackage(packageName);
     }
@@ -599,6 +615,7 @@
      * @param status the RollbackManager.STATUS_* code with the failure.
      * @param message the failure message.
      */
+    @AnyThread
     static void sendFailure(Context context, IntentSender statusReceiver,
             @RollbackManager.Status int status, String message) {
         Slog.e(TAG, message);
@@ -614,6 +631,7 @@
 
     // Check to see if anything needs expiration, and if so, expire it.
     // Schedules future expiration as appropriate.
+    @WorkerThread
     private void runExpiration() {
         Instant now = Instant.now();
         Instant oldest = null;
@@ -649,10 +667,12 @@
      * Schedules an expiration check to be run after the given duration in
      * milliseconds has gone by.
      */
+    @AnyThread
     private void scheduleExpiration(long duration) {
         getHandler().postDelayed(() -> runExpiration(), duration);
     }
 
+    @AnyThread
     private Handler getHandler() {
         return mHandlerThread.getThreadHandler();
     }
@@ -660,6 +680,7 @@
     // Returns true if <code>session</code> has installFlags and code path
     // matching the installFlags and new package code path given to
     // enableRollback.
+    @WorkerThread
     private boolean sessionMatchesForEnableRollback(PackageInstaller.SessionInfo session,
             int installFlags, File newPackageCodePath) {
         if (session == null || session.resolvedBaseCodePath == null) {
@@ -674,6 +695,7 @@
         return false;
     }
 
+    @AnyThread
     private Context getContextAsUser(UserHandle user) {
         try {
             return mContext.createPackageContextAsUser(mContext.getPackageName(), 0, user);
@@ -693,6 +715,7 @@
      * @param token the distinct rollback token sent by package manager.
      * @return true if enabling the rollback succeeds, false otherwise.
      */
+    @WorkerThread
     private boolean enableRollback(
             int installFlags, File newPackageCodePath, @UserIdInt int user, int token) {
         if (LOCAL_LOGV) {
@@ -780,6 +803,7 @@
         return enableRollbackForPackageSession(newRollback.rollback, packageSession);
     }
 
+    @WorkerThread
     private void removeRollbackForPackageSessionId(int sessionId) {
         if (LOCAL_LOGV) {
             Slog.v(TAG, "removeRollbackForPackageSessionId=" + sessionId);
@@ -814,6 +838,7 @@
      *
      * @return true on success, false on failure.
      */
+    @WorkerThread
     private boolean enableRollbackForPackageSession(Rollback rollback,
             PackageInstaller.SessionInfo session) {
         // TODO: Don't attempt to enable rollback for split installs.
@@ -888,6 +913,7 @@
         });
     }
 
+    @WorkerThread
     private void snapshotUserDataInternal(String packageName, int[] userIds) {
         if (LOCAL_LOGV) {
             Slog.v(TAG, "snapshotUserData pkg=" + packageName
@@ -907,6 +933,7 @@
         }
     }
 
+    @WorkerThread
     private void restoreUserDataInternal(
             String packageName, int[] userIds, int appId, String seInfo) {
         if (LOCAL_LOGV) {
@@ -1021,6 +1048,7 @@
      * Returns true if the installer is allowed to enable rollback for the
      * given named package, false otherwise.
      */
+    @AnyThread
     private boolean enableRollbackAllowed(String installerPackageName, String packageName) {
         if (installerPackageName == null) {
             return false;
@@ -1043,6 +1071,7 @@
     /**
      * Returns true is this package is eligible for enabling rollback.
      */
+    @AnyThread
     private boolean isRollbackWhitelisted(String packageName) {
         // TODO: Remove #isModule when the white list is ready.
         return SystemConfig.getInstance().getRollbackWhitelistedPackages().contains(packageName)
@@ -1051,6 +1080,7 @@
     /**
      * Returns true if the package name is the name of a module.
      */
+    @AnyThread
     private boolean isModule(String packageName) {
         PackageManager pm = mContext.getPackageManager();
         final ModuleInfo moduleInfo;
@@ -1067,6 +1097,7 @@
      * Gets the version of the package currently installed.
      * Returns -1 if the package is not currently installed.
      */
+    @AnyThread
     private long getInstalledPackageVersion(String packageName) {
         PackageInfo pkgInfo;
         try {
@@ -1083,6 +1114,7 @@
      *
      * @throws PackageManager.NameNotFoundException if no such package is installed.
      */
+    @AnyThread
     private PackageInfo getPackageInfo(String packageName)
             throws PackageManager.NameNotFoundException {
         PackageManager pm = mContext.getPackageManager();
@@ -1097,6 +1129,7 @@
         }
     }
 
+    @WorkerThread
     private class SessionCallback extends PackageInstaller.SessionCallback {
 
         @Override
@@ -1149,6 +1182,7 @@
      * @return the Rollback instance for a successfully enable-completed rollback,
      * or null on error.
      */
+    @WorkerThread
     private Rollback completeEnableRollback(NewRollback newRollback) {
         Rollback rollback = newRollback.rollback;
         if (LOCAL_LOGV) {
@@ -1185,6 +1219,7 @@
         return rollback;
     }
 
+    @WorkerThread
     @GuardedBy("rollback.getLock")
     private void makeRollbackAvailable(Rollback rollback) {
         if (LOCAL_LOGV) {
@@ -1205,6 +1240,7 @@
     /*
      * Returns the rollback with the given rollbackId, if any.
      */
+    @WorkerThread
     private Rollback getRollbackForId(int rollbackId) {
         synchronized (mLock) {
             for (int i = 0; i < mRollbacks.size(); ++i) {
@@ -1218,6 +1254,7 @@
         return null;
     }
 
+    @WorkerThread
     @GuardedBy("mLock")
     private int allocateRollbackIdLocked() {
         int n = 0;
@@ -1247,6 +1284,7 @@
         }
     }
 
+    @AnyThread
     private void enforceManageRollbacks(@NonNull String message) {
         if ((PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(
                         Manifest.permission.MANAGE_ROLLBACKS))
@@ -1370,6 +1408,7 @@
         }
     }
 
+    @WorkerThread
     @GuardedBy("mLock")
     private NewRollback createNewRollbackLocked(PackageInstaller.SessionInfo parentSession) {
         int rollbackId = allocateRollbackIdLocked();
@@ -1411,6 +1450,7 @@
      * Returns null if no NewRollback is found for the given package
      * session.
      */
+    @WorkerThread
     @GuardedBy("mLock")
     NewRollback getNewRollbackForPackageSessionLocked(int packageSessionId) {
         // We expect mNewRollbacks to be a very small list; linear search
diff --git a/services/core/java/com/android/server/utils/quota/UptcMap.java b/services/core/java/com/android/server/utils/quota/UptcMap.java
index 7b49913..80f4f0a 100644
--- a/services/core/java/com/android/server/utils/quota/UptcMap.java
+++ b/services/core/java/com/android/server/utils/quota/UptcMap.java
@@ -22,6 +22,7 @@
 import android.util.SparseArrayMap;
 
 import java.util.function.Consumer;
+import java.util.function.Function;
 
 /**
  * A SparseArrayMap of ArrayMaps, which is suitable for holding userId-packageName-tag combination
@@ -95,6 +96,23 @@
     }
 
     /**
+     * Returns the saved object for the given UPTC. If there was no saved object, it will create a
+     * new object using creator, insert it, and return it.
+     */
+    @Nullable
+    public T getOrCreate(int userId, @NonNull String packageName, @Nullable String tag,
+            Function<Void, T> creator) {
+        final ArrayMap<String, T> data = mData.get(userId, packageName);
+        if (data == null || !data.containsKey(tag)) {
+            // We've never inserted data for this combination before. Create a new object.
+            final T val = creator.apply(null);
+            add(userId, packageName, tag, val);
+            return val;
+        }
+        return data.get(tag);
+    }
+
+    /**
      * Returns the index for which {@link #getUserIdAtIndex(int)} would return the specified userId,
      * or a negative number if the specified userId is not mapped.
      */
@@ -160,4 +178,26 @@
             }
         });
     }
+
+    public void forEach(UptcDataConsumer<T> consumer) {
+        final int uCount = userCount();
+        for (int u = 0; u < uCount; ++u) {
+            final int userId = getUserIdAtIndex(u);
+
+            final int pkgCount = packageCountForUser(userId);
+            for (int p = 0; p < pkgCount; ++p) {
+                final String pkgName = getPackageNameAtIndex(u, p);
+
+                final int tagCount = tagCountForUserAndPackage(userId, pkgName);
+                for (int t = 0; t < tagCount; ++t) {
+                    final String tag = getTagAtIndex(u, p, t);
+                    consumer.accept(userId, pkgName, tag, get(userId, pkgName, tag));
+                }
+            }
+        }
+    }
+
+    interface UptcDataConsumer<D> {
+        void accept(int userId, @NonNull String packageName, @Nullable String tag, @Nullable D obj);
+    }
 }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 67fe149..fcab796 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -4802,10 +4802,8 @@
             } else {
                 final int count = mChildren.size();
                 for (int i = 0; i < count; i++) {
-                    Slog.d(TAG, "child " + mChildren.get(i));
                     final WindowContainer child = mChildren.get(i);
                     if (skipTraverseChild(child)) {
-                        Slog.d(TAG, "child skipped");
                         continue;
                     }
 
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 694a73d..f9ad03f 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -2192,10 +2192,13 @@
         final boolean attachedInParent = attached != null && !layoutInScreen;
         final boolean requestedFullscreen = (fl & FLAG_FULLSCREEN) != 0
                 || (requestedSysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0
-                || !win.getClientInsetsState().getSource(ITYPE_STATUS_BAR).isVisible();
+                || (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL
+                        && !win.getRequestedInsetsState().getSource(ITYPE_STATUS_BAR).isVisible());
         final boolean requestedHideNavigation =
                 (requestedSysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
-                        || !win.getClientInsetsState().getSource(ITYPE_NAVIGATION_BAR).isVisible();
+                || (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL
+                        && !win.getRequestedInsetsState().getSource(ITYPE_NAVIGATION_BAR)
+                                .isVisible());
 
         // TYPE_BASE_APPLICATION windows are never considered floating here because they don't get
         // cropped / shifted to the displayFrame in WindowState.
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index af84836..a008963 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -66,10 +66,11 @@
         }
         mStatusBar.setVisible(focusedWin == null
                 || focusedWin != getStatusControlTarget(focusedWin)
-                || focusedWin.getClientInsetsState().getSource(ITYPE_STATUS_BAR).isVisible());
+                || focusedWin.getRequestedInsetsState().getSource(ITYPE_STATUS_BAR).isVisible());
         mNavBar.setVisible(focusedWin == null
                 || focusedWin != getNavControlTarget(focusedWin)
-                || focusedWin.getClientInsetsState().getSource(ITYPE_NAVIGATION_BAR).isVisible());
+                || focusedWin.getRequestedInsetsState().getSource(ITYPE_NAVIGATION_BAR)
+                        .isVisible());
     }
 
     boolean isHidden(@InternalInsetsType int type) {
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 5198602..3b349b8 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -463,7 +463,7 @@
             final WindowState windowState = mService.windowForClientLocked(this, window,
                     false /* throwOnError */);
             if (windowState != null) {
-                windowState.setClientInsetsState(state);
+                windowState.updateRequestedInsetsState(state);
                 windowState.getDisplayContent().getInsetsPolicy().onInsetsModified(
                         windowState, state);
             }
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index e4744db..4cb5de4 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -470,7 +470,7 @@
         final LayoutParams attrs = mainWindow.getAttrs();
         final SystemBarBackgroundPainter decorPainter = new SystemBarBackgroundPainter(attrs.flags,
                 attrs.privateFlags, attrs.systemUiVisibility, task.getTaskDescription(),
-                mFullSnapshotScale, mainWindow.getClientInsetsState());
+                mFullSnapshotScale, mainWindow.getRequestedInsetsState());
         final int width = (int) (task.getBounds().width() * mFullSnapshotScale);
         final int height = (int) (task.getBounds().height() * mFullSnapshotScale);
 
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 5b458d8..e2a21a9 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -222,7 +222,7 @@
         final TaskSnapshotSurface snapshotSurface = new TaskSnapshotSurface(service, window,
                 surfaceControl, snapshot, layoutParams.getTitle(), taskDescription, sysUiVis,
                 windowFlags, windowPrivateFlags, taskBounds,
-                currentOrientation, topFullscreenOpaqueWindow.getClientInsetsState());
+                currentOrientation, topFullscreenOpaqueWindow.getRequestedInsetsState());
         window.setOuter(snapshotSurface);
         try {
             session.relayout(window, window.mSeq, layoutParams, -1, -1, View.VISIBLE, 0, -1,
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 2ac1f39..00ef95a 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -210,6 +210,7 @@
 import android.view.InputEvent;
 import android.view.InputEventReceiver;
 import android.view.InputWindowHandle;
+import android.view.InsetsSource;
 import android.view.InsetsState;
 import android.view.Surface.Rotation;
 import android.view.SurfaceControl;
@@ -650,17 +651,29 @@
     private boolean mIsDimming = false;
 
     private @Nullable InsetsSourceProvider mControllableInsetProvider;
-    private InsetsState mClientInsetsState;
+    private InsetsState mRequestedInsetsState;
 
     private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f;
     private KeyInterceptionInfo mKeyInterceptionInfo;
 
-    InsetsState getClientInsetsState() {
-        return mClientInsetsState;
+    /**
+     * @return The insets state as requested by the client, i.e. the dispatched insets state
+     *         for which the visibilities are overridden with what the client requested.
+     */
+    InsetsState getRequestedInsetsState() {
+        return mRequestedInsetsState;
     }
 
-    void setClientInsetsState(InsetsState state) {
-        mClientInsetsState = state;
+    /**
+     * @see #getRequestedInsetsState()
+     */
+    void updateRequestedInsetsState(InsetsState state) {
+
+        // Only update the sources the client is actually controlling.
+        for (int i = state.getSourcesCount(); i >= 0; i--) {
+            final InsetsSource source = state.sourceAt(i);
+            mRequestedInsetsState.addSource(source);
+        }
     }
 
     void seamlesslyRotateIfAllowed(Transaction transaction, @Rotation int oldRotation,
@@ -779,7 +792,7 @@
         mSeq = seq;
         mPowerManagerWrapper = powerManagerWrapper;
         mForceSeamlesslyRotate = token.mRoundedCornerOverlay;
-        mClientInsetsState =
+        mRequestedInsetsState =
                 getDisplayContent().getInsetsPolicy().getInsetsForDispatch(this);
         if (DEBUG) {
             Slog.v(TAG, "Window " + this + " client=" + c.asBinder()
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index fee29db..1ad6e86 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -138,6 +138,7 @@
         "android.hardware.thermal@1.0",
         "android.hardware.tv.cec@1.0",
         "android.hardware.tv.input@1.0",
+        "android.hardware.vibrator-cpp",
         "android.hardware.vibrator@1.0",
         "android.hardware.vibrator@1.1",
         "android.hardware.vibrator@1.2",
@@ -148,7 +149,6 @@
         "android.system.suspend@1.0",
         "service.incremental",
         "suspend_control_aidl_interface-cpp",
-        "vintf-vibrator-cpp",
     ],
 
     static_libs: [
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 5028585..e081ca3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -421,8 +421,10 @@
                 .setWindow(statusBar, null /* frameProvider */);
         mDisplayContent.getInsetsStateController().onBarControlTargetChanged(
                 app, null /* fakeTopControlling */, app, null /* fakeNavControlling */);
+        final InsetsSource source = new InsetsSource(ITYPE_STATUS_BAR);
+        source.setVisible(false);
         mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_STATUS_BAR)
-                .onInsetsModified(app, new InsetsSource(ITYPE_STATUS_BAR));
+                .onInsetsModified(app, source);
         waitUntilHandlersIdle();
         assertFalse(statusBar.isVisible());
     }
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 0becaf2..8808339 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -502,51 +502,116 @@
     //**********************************************************************************************
 
     /**
-     * Define IMS Audio Codec
+     * Indicates that the audio codec is currently not specified or is unknown.
      */
-    // Current audio codec is NONE
     public static final int AUDIO_CODEC_NONE = ImsStreamMediaProfile.AUDIO_QUALITY_NONE; // 0
-    // Current audio codec is AMR
+    /**
+     * Adaptive Multi-rate audio codec.
+     */
     public static final int AUDIO_CODEC_AMR = ImsStreamMediaProfile.AUDIO_QUALITY_AMR; // 1
-    // Current audio codec is AMR_WB
+    /**
+     * Adaptive Multi-rate wideband audio codec.
+     */
     public static final int AUDIO_CODEC_AMR_WB = ImsStreamMediaProfile.AUDIO_QUALITY_AMR_WB; // 2
-    // Current audio codec is QCELP13K
+    /**
+     * Qualcomm code-excited linear prediction 13 kilobit audio codec.
+     */
     public static final int AUDIO_CODEC_QCELP13K = ImsStreamMediaProfile.AUDIO_QUALITY_QCELP13K; //3
-    // Current audio codec is EVRC
+    /**
+     * Enhanced Variable Rate Codec.  See 3GPP2 C.S0014-A.
+     */
     public static final int AUDIO_CODEC_EVRC = ImsStreamMediaProfile.AUDIO_QUALITY_EVRC; // 4
-    // Current audio codec is EVRC_B
+    /**
+     * Enhanced Variable Rate Codec B.  Commonly used on CDMA networks.
+     */
     public static final int AUDIO_CODEC_EVRC_B = ImsStreamMediaProfile.AUDIO_QUALITY_EVRC_B; // 5
-    // Current audio codec is EVRC_WB
+    /**
+     * Enhanced Variable Rate Wideband Codec.  See RFC5188.
+     */
     public static final int AUDIO_CODEC_EVRC_WB = ImsStreamMediaProfile.AUDIO_QUALITY_EVRC_WB; // 6
-    // Current audio codec is EVRC_NW
+    /**
+     * Enhanced Variable Rate Narrowband-Wideband Codec.
+     */
     public static final int AUDIO_CODEC_EVRC_NW = ImsStreamMediaProfile.AUDIO_QUALITY_EVRC_NW; // 7
-    // Current audio codec is GSM_EFR
+    /**
+     * GSM Enhanced Full-Rate audio codec, also known as GSM-EFR, GSM 06.60, or simply EFR.
+     */
     public static final int AUDIO_CODEC_GSM_EFR = ImsStreamMediaProfile.AUDIO_QUALITY_GSM_EFR; // 8
-    // Current audio codec is GSM_FR
+    /**
+     * GSM Full-Rate audio codec, also known as GSM-FR, GSM 06.10, GSM, or simply FR.
+     */
     public static final int AUDIO_CODEC_GSM_FR = ImsStreamMediaProfile.AUDIO_QUALITY_GSM_FR; // 9
-    // Current audio codec is GSM_HR
+    /**
+     * GSM Half Rate audio codec.
+     */
     public static final int AUDIO_CODEC_GSM_HR = ImsStreamMediaProfile.AUDIO_QUALITY_GSM_HR; // 10
-    // Current audio codec is G711U
+    /**
+     * ITU-T G711U audio codec.
+     */
     public static final int AUDIO_CODEC_G711U = ImsStreamMediaProfile.AUDIO_QUALITY_G711U; // 11
-    // Current audio codec is G723
+    /**
+     * ITU-T G723 audio codec.
+     */
     public static final int AUDIO_CODEC_G723 = ImsStreamMediaProfile.AUDIO_QUALITY_G723; // 12
-    // Current audio codec is G711A
+    /**
+     * ITU-T G711A audio codec.
+     */
     public static final int AUDIO_CODEC_G711A = ImsStreamMediaProfile.AUDIO_QUALITY_G711A; // 13
-    // Current audio codec is G722
+    /**
+     * ITU-T G722 audio codec.
+     */
     public static final int AUDIO_CODEC_G722 = ImsStreamMediaProfile.AUDIO_QUALITY_G722; // 14
-    // Current audio codec is G711AB
+    /**
+     * ITU-T G711AB audio codec.
+     */
     public static final int AUDIO_CODEC_G711AB = ImsStreamMediaProfile.AUDIO_QUALITY_G711AB; // 15
-    // Current audio codec is G729
+    /**
+     * ITU-T G729 audio codec.
+     */
     public static final int AUDIO_CODEC_G729 = ImsStreamMediaProfile.AUDIO_QUALITY_G729; // 16
-    // Current audio codec is EVS_NB
+    /**
+     * Enhanced Voice Services Narrowband audio codec.  See 3GPP TS 26.441.
+     */
     public static final int AUDIO_CODEC_EVS_NB = ImsStreamMediaProfile.AUDIO_QUALITY_EVS_NB; // 17
-    // Current audio codec is EVS_WB
+    /**
+     * Enhanced Voice Services Wideband audio codec.  See 3GPP TS 26.441.
+     */
     public static final int AUDIO_CODEC_EVS_WB = ImsStreamMediaProfile.AUDIO_QUALITY_EVS_WB; // 18
-    // Current audio codec is EVS_SWB
+    /**
+     * Enhanced Voice Services Super-Wideband audio codec.  See 3GPP TS 26.441.
+     */
     public static final int AUDIO_CODEC_EVS_SWB = ImsStreamMediaProfile.AUDIO_QUALITY_EVS_SWB; // 19
-    // Current audio codec is EVS_FB
+    /**
+     * Enhanced Voice Services Fullband audio codec.  See 3GPP TS 26.441.
+     */
     public static final int AUDIO_CODEC_EVS_FB = ImsStreamMediaProfile.AUDIO_QUALITY_EVS_FB; // 20
 
+    /**@hide*/
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = "AUDIO_CODEC_", value = {
+            AUDIO_CODEC_NONE,
+            AUDIO_CODEC_AMR,
+            AUDIO_CODEC_AMR_WB,
+            AUDIO_CODEC_QCELP13K,
+            AUDIO_CODEC_EVRC,
+            AUDIO_CODEC_EVRC_B,
+            AUDIO_CODEC_EVRC_WB,
+            AUDIO_CODEC_EVRC_NW,
+            AUDIO_CODEC_GSM_EFR,
+            AUDIO_CODEC_GSM_FR,
+            AUDIO_CODEC_GSM_HR,
+            AUDIO_CODEC_G711U,
+            AUDIO_CODEC_G723,
+            AUDIO_CODEC_G711A,
+            AUDIO_CODEC_G722,
+            AUDIO_CODEC_G711AB,
+            AUDIO_CODEC_G729,
+            AUDIO_CODEC_EVS_NB,
+            AUDIO_CODEC_EVS_SWB,
+            AUDIO_CODEC_EVS_FB
+    })
+    public @interface AudioCodec {}
+
     /**
      * Connection extra key used to store the last forwarded number associated with the current
      * connection.  Used to communicate to the user interface that the connection was forwarded via
@@ -640,10 +705,10 @@
             "android.telecom.extra.IS_RTT_AUDIO_PRESENT";
 
     /**
-     * The audio codec in use for the current {@link Connection}, if known. Valid values include
-     * {@link #AUDIO_CODEC_AMR_WB} and {@link #AUDIO_CODEC_EVS_WB}.
+     * The audio codec in use for the current {@link Connection}, if known.  Examples of valid
+     * values include {@link #AUDIO_CODEC_AMR_WB} and {@link #AUDIO_CODEC_EVS_WB}.
      */
-    public static final String EXTRA_AUDIO_CODEC =
+    public static final @AudioCodec String EXTRA_AUDIO_CODEC =
             "android.telecom.extra.AUDIO_CODEC";
 
     /**
diff --git a/telephony/common/com/android/internal/telephony/SmsApplication.java b/telephony/common/com/android/internal/telephony/SmsApplication.java
index 70ce1bf..0275cb9 100644
--- a/telephony/common/com/android/internal/telephony/SmsApplication.java
+++ b/telephony/common/com/android/internal/telephony/SmsApplication.java
@@ -44,6 +44,7 @@
 import android.telephony.TelephonyManager;
 import android.util.Log;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 
@@ -65,10 +66,10 @@
  */
 public final class SmsApplication {
     static final String LOG_TAG = "SmsApplication";
-    private static final String PHONE_PACKAGE_NAME = "com.android.phone";
-    private static final String BLUETOOTH_PACKAGE_NAME = "com.android.bluetooth";
-    private static final String MMS_SERVICE_PACKAGE_NAME = "com.android.mms.service";
-    private static final String TELEPHONY_PROVIDER_PACKAGE_NAME = "com.android.providers.telephony";
+    public static final String PHONE_PACKAGE_NAME = "com.android.phone";
+    public static final String BLUETOOTH_PACKAGE_NAME = "com.android.bluetooth";
+    public static final String MMS_SERVICE_PACKAGE_NAME = "com.android.mms.service";
+    public static final String TELEPHONY_PROVIDER_PACKAGE_NAME = "com.android.providers.telephony";
 
     private static final String SCHEME_SMS = "sms";
     private static final String SCHEME_SMSTO = "smsto";
@@ -77,13 +78,13 @@
     private static final boolean DEBUG = false;
     private static final boolean DEBUG_MULTIUSER = false;
 
-    private static final int[] DEFAULT_APP_EXCLUSIVE_APPOPS = {
-            AppOpsManager.OP_READ_SMS,
-            AppOpsManager.OP_WRITE_SMS,
-            AppOpsManager.OP_RECEIVE_SMS,
-            AppOpsManager.OP_RECEIVE_WAP_PUSH,
-            AppOpsManager.OP_SEND_SMS,
-            AppOpsManager.OP_READ_CELL_BROADCASTS
+    private static final String[] DEFAULT_APP_EXCLUSIVE_APPOPS = {
+            AppOpsManager.OPSTR_READ_SMS,
+            AppOpsManager.OPSTR_WRITE_SMS,
+            AppOpsManager.OPSTR_RECEIVE_SMS,
+            AppOpsManager.OPSTR_RECEIVE_WAP_PUSH,
+            AppOpsManager.OPSTR_SEND_SMS,
+            AppOpsManager.OPSTR_READ_CELL_BROADCASTS
     };
 
     private static SmsPackageMonitor sSmsPackageMonitor = null;
@@ -496,7 +497,7 @@
 
         // If we found a package, make sure AppOps permissions are set up correctly
         if (applicationData != null) {
-            // We can only call checkOp if we are privileged (updateIfNeeded) or if the app we
+            // We can only call unsafeCheckOp if we are privileged (updateIfNeeded) or if the app we
             // are checking is for our current uid. Doing this check from the unprivileged current
             // SMS app allows us to tell the current SMS app that it is not in a good state and
             // needs to ask to be the current SMS app again to work properly.
@@ -550,23 +551,23 @@
         // apps, all of them should be able to write to telephony provider.
         // This is to allow the proxy package permission check in telephony provider
         // to pass.
-        for (int appop : DEFAULT_APP_EXCLUSIVE_APPOPS) {
-            appOps.setUidMode(appop, Process.PHONE_UID, AppOpsManager.MODE_ALLOWED);
+        for (String opStr : DEFAULT_APP_EXCLUSIVE_APPOPS) {
+            appOps.setUidMode(opStr, Process.PHONE_UID, AppOpsManager.MODE_ALLOWED);
         }
     }
 
     private static boolean tryFixExclusiveSmsAppops(Context context,
             SmsApplicationData applicationData, boolean updateIfNeeded) {
         AppOpsManager appOps = context.getSystemService(AppOpsManager.class);
-        for (int appOp : DEFAULT_APP_EXCLUSIVE_APPOPS) {
-            int mode = appOps.checkOp(appOp, applicationData.mUid,
+        for (String opStr : DEFAULT_APP_EXCLUSIVE_APPOPS) {
+            int mode = appOps.unsafeCheckOp(opStr, applicationData.mUid,
                     applicationData.mPackageName);
             if (mode != AppOpsManager.MODE_ALLOWED) {
                 Rlog.e(LOG_TAG, applicationData.mPackageName + " lost "
-                        + AppOpsManager.modeToName(appOp) + ": "
+                        + opStr + ": "
                         + (updateIfNeeded ? " (fixing)" : " (no permission to fix)"));
                 if (updateIfNeeded) {
-                    appOps.setUidMode(appOp, applicationData.mUid, AppOpsManager.MODE_ALLOWED);
+                    appOps.setUidMode(opStr, applicationData.mUid, AppOpsManager.MODE_ALLOWED);
                 } else {
                     return false;
                 }
@@ -752,7 +753,7 @@
         }
         try {
             PackageInfo info = packageManager.getPackageInfo(packageName, 0);
-            int mode = appOps.checkOp(AppOpsManager.OP_WRITE_SMS, info.applicationInfo.uid,
+            int mode = appOps.unsafeCheckOp(AppOpsManager.OPSTR_WRITE_SMS, info.applicationInfo.uid,
                     packageName);
             if (mode != AppOpsManager.MODE_ALLOWED) {
                 Rlog.w(LOG_TAG, packageName + " does not have OP_WRITE_SMS:  (fixing)");
@@ -768,8 +769,8 @@
 
     private static void setExclusiveAppops(String pkg, AppOpsManager appOpsManager, int uid,
             int mode) {
-        for (int appop : DEFAULT_APP_EXCLUSIVE_APPOPS) {
-            appOpsManager.setUidMode(appop, uid, mode);
+        for (String opStr : DEFAULT_APP_EXCLUSIVE_APPOPS) {
+            appOpsManager.setUidMode(opStr, uid, mode);
         }
     }
 
@@ -894,6 +895,7 @@
      * @param userId target user ID.
      * @return component name of the app and class to deliver SMS messages to
      */
+    @VisibleForTesting
     public static ComponentName getDefaultSmsApplicationAsUser(Context context,
             boolean updateIfNeeded, int userId) {
         final long token = Binder.clearCallingIdentity();
diff --git a/telephony/common/com/google/android/mms/pdu/PduPersister.java b/telephony/common/com/google/android/mms/pdu/PduPersister.java
index b237705..8efca0e 100755
--- a/telephony/common/com/google/android/mms/pdu/PduPersister.java
+++ b/telephony/common/com/google/android/mms/pdu/PduPersister.java
@@ -34,6 +34,7 @@
 import android.provider.Telephony.MmsSms.PendingMessages;
 import android.provider.Telephony.Threads;
 import android.telephony.PhoneNumberUtils;
+import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
@@ -1448,9 +1449,9 @@
         final Set<String> myPhoneNumbers = new HashSet<String>();
         if (excludeMyNumber) {
             // Build a list of my phone numbers from the various sims.
-            for (int subid : subscriptionManager.getActiveSubscriptionIdList()) {
+            for (SubscriptionInfo subInfo : subscriptionManager.getActiveSubscriptionInfoList()) {
                 final String myNumber = mContext.getSystemService(TelephonyManager.class).
-                        createForSubscriptionId(subid).getLine1Number();
+                        createForSubscriptionId(subInfo.getSubscriptionId()).getLine1Number();
                 if (myNumber != null) {
                     myPhoneNumbers.add(myNumber);
                 }
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index 9aafc1b..3718bc7 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -17,6 +17,7 @@
 package android.telephony;
 
 import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.os.Build;
 import android.os.Bundle;
@@ -275,8 +276,8 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage
-    public SignalStrength(SignalStrength s) {
+    @SystemApi
+    public SignalStrength(@NonNull SignalStrength s) {
         copyFrom(s);
     }
 
@@ -332,17 +333,16 @@
     /**
      * {@link Parcelable.Creator}
      *
-     * @hide
      */
-    @UnsupportedAppUsage
-    public static final @android.annotation.NonNull Parcelable.Creator<SignalStrength> CREATOR = new Parcelable.Creator() {
-        public SignalStrength createFromParcel(Parcel in) {
-            return new SignalStrength(in);
-        }
+    public static final @android.annotation.NonNull Parcelable.Creator<SignalStrength> CREATOR =
+            new Parcelable.Creator<SignalStrength>() {
+                public SignalStrength createFromParcel(Parcel in) {
+                    return new SignalStrength(in);
+                }
 
-        public SignalStrength[] newArray(int size) {
-            return new SignalStrength[size];
-        }
+                public SignalStrength[] newArray(int size) {
+                    return new SignalStrength[size];
+                }
     };
 
     /**
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 7215ef8..3e576dc 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -2504,22 +2504,31 @@
     public static final String MESSAGE_STATUS_READ = "read";
 
     /**
-     * Get carrier-dependent configuration values.
+     * Get carrier-dependent MMS configuration values.
      *
      * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
-     * applications or the Telephony framework and will never trigger an SMS disambiguation
-     * dialog. If this method is called on a device that has multiple active subscriptions, this
-     * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
-     * default subscription is defined, the subscription ID associated with this message will be
-     * INVALID, which will result in the operation being completed on the subscription associated
-     * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
-     * operation is performed on the correct subscription.
+     * applications or the Telephony framework and will never trigger an SMS disambiguation dialog.
+     * If this method is called on a device that has multiple active subscriptions, this {@link
+     * SmsManager} instance has been created with {@link #getDefault()}, and no user-defined default
+     * subscription is defined, the subscription ID associated with this message will be INVALID,
+     * which will result in the operation being completed on the subscription associated with
+     * logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the operation is
+     * performed on the correct subscription.
      * </p>
      *
-     * @return bundle key/values pairs of configuration values
+     * @return the bundle key/values pairs that contains MMS configuration values
      */
+    @Nullable
     public Bundle getCarrierConfigValues() {
-        return MmsManager.getInstance().getCarrierConfigValues(getSubscriptionId());
+        try {
+            ISms iSms = getISmsService();
+            if (iSms != null) {
+                return iSms.getCarrierConfigValuesForSubscriber(getSubscriptionId());
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+        return null;
     }
 
     /**
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index f6b3958..a44128c 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -3302,31 +3302,6 @@
         return subId;
     }
 
-    /**
-     * Set whether a subscription always allows MMS connection. If true, MMS network
-     * request will be accepted by telephony even if user turns "mobile data" off
-     * on this subscription.
-     *
-     * @param subId which subscription it's setting to.
-     * @param alwaysAllow whether Mms data is always allowed.
-     * @return whether operation is successful.
-     *
-     * @hide
-     */
-    public boolean setAlwaysAllowMmsData(int subId, boolean alwaysAllow) {
-        try {
-            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
-            if (iSub != null) {
-                return iSub.setAlwaysAllowMmsData(subId, alwaysAllow);
-            }
-        } catch (RemoteException ex) {
-            if (!isSystemProcess()) {
-                ex.rethrowAsRuntimeException();
-            }
-        }
-        return false;
-    }
-
     private interface CallISubMethodHelper {
         int callMethod(ISub iSub) throws RemoteException;
     }
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index ba6e7e9..8272b0a 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -10600,7 +10600,8 @@
      *
      * @hide
      */
-    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public boolean isManualNetworkSelectionAllowed() {
         try {
             ITelephony telephony = getITelephony();
@@ -12000,7 +12001,7 @@
      *  1) User data is turned on, or
      *  2) APN is un-metered for this subscription, or
      *  3) APN type is whitelisted. E.g. MMS is whitelisted if
-     *  {@link SubscriptionManager#setAlwaysAllowMmsData} is turned on.
+     *  {@link #setAlwaysAllowMmsData(boolean)} is turned on.
      *
      * @param apnType Value indicating the apn type. Apn types are defined in {@link ApnSetting}.
      * @return whether data is enabled for a apn type.
@@ -12124,4 +12125,30 @@
         }
         return false;
     }
+
+    /**
+     * Set whether the specific sim card always allows MMS connection. If true, MMS network
+     * request will be accepted by telephony even if user turns "mobile data" off
+     * on this specific sim card.
+     *
+     * @param alwaysAllow whether Mms data is always allowed.
+     * @return whether operation is successful.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public boolean setAlwaysAllowMmsData(boolean alwaysAllow) {
+        try {
+            ITelephony service = getITelephony();
+            if (service != null) {
+                return service.setAlwaysAllowMmsData(getSubId(), alwaysAllow);
+            }
+        } catch (RemoteException ex) {
+            if (!isSystemProcess()) {
+                ex.rethrowAsRuntimeException();
+            }
+        }
+        return false;
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl
index 9f4d066..c07a171 100644
--- a/telephony/java/com/android/internal/telephony/ISms.aidl
+++ b/telephony/java/com/android/internal/telephony/ISms.aidl
@@ -1,18 +1,18 @@
 /*
-** Copyright 2007, 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.
-*/
+ * Copyright 2007, 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;
 
@@ -22,7 +22,7 @@
 import com.android.internal.telephony.SmsRawData;
 
 /**
- * Interface for applications to access the ICC phone book.
+ * Service interface to handle SMS API requests
  *
  * See also SmsManager.java.
  */
@@ -542,6 +542,13 @@
                 in List<PendingIntent> deliveryIntents);
 
     /**
+     * Get carrier-dependent configuration values.
+     *
+     * @param subId the subscription Id
+     */
+    Bundle getCarrierConfigValuesForSubscriber(int subId);
+
+    /**
      * Create an app-only incoming SMS request for the calling package.
      *
      * If an incoming text contains the token returned by this method the provided
diff --git a/telephony/java/com/android/internal/telephony/ISmsImplBase.java b/telephony/java/com/android/internal/telephony/ISmsImplBase.java
index 2430d82..ddd3457 100644
--- a/telephony/java/com/android/internal/telephony/ISmsImplBase.java
+++ b/telephony/java/com/android/internal/telephony/ISmsImplBase.java
@@ -18,6 +18,7 @@
 
 import android.app.PendingIntent;
 import android.net.Uri;
+import android.os.Bundle;
 
 import java.util.List;
 
@@ -185,6 +186,11 @@
     }
 
     @Override
+    public Bundle getCarrierConfigValuesForSubscriber(int subId) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public String createAppSpecificSmsToken(int subId, String callingPkg, PendingIntent intent) {
         throw new UnsupportedOperationException();
     }
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index cc02a40..571efce 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -295,8 +295,6 @@
 
     boolean isActiveSubId(int subId, String callingPackage, String callingFeatureId);
 
-    boolean setAlwaysAllowMmsData(int subId, boolean alwaysAllow);
-
     int getActiveDataSubscriptionId();
 
     boolean canDisablePhysicalSubscription();
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 9d721fc..b846a10 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2118,6 +2118,11 @@
     boolean isDataAllowedInVoiceCall(int subId);
 
     /**
+     * Set whether a subscription always allows MMS connection.
+     */
+    boolean setAlwaysAllowMmsData(int subId, boolean allow);
+
+    /**
      * Command line command to enable or disable handling of CEP data for test purposes.
      */
     oneway void setCepEnabled(boolean isCepEnabled);
diff --git a/tests/TelephonyCommonTests/Android.bp b/tests/TelephonyCommonTests/Android.bp
new file mode 100644
index 0000000..16189c8
--- /dev/null
+++ b/tests/TelephonyCommonTests/Android.bp
@@ -0,0 +1,48 @@
+//
+// 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.
+//
+
+android_test {
+    name: "TelephonyCommonTests",
+    srcs: [
+        ":framework-telephony-common-sources",
+        "**/*.java",
+    ],
+    static_libs: [
+        "mockito-target-extended",
+        "androidx.test.rules",
+        "truth-prebuilt",
+        "platform-test-annotations",
+        "androidx.core_core",
+        "androidx.fragment_fragment",
+        "androidx.test.ext.junit"
+    ],
+
+    jni_libs: ["libdexmakerjvmtiagent"],
+
+    // We need to rename SmsApplication to the test package or else it'll get clobbered by the
+    // hidden api checker
+    jarjar_rules: "jarjar-rules.txt",
+
+    // Uncomment this and comment out the jarjar rule if you want to attach a debugger and step
+    // through the renamed classes.
+    //platform_apis: true,
+
+    libs: [
+        "android.test.runner",
+        "android.test.mock",
+        "android.test.base",
+    ],
+}
diff --git a/tests/TelephonyCommonTests/AndroidManifest.xml b/tests/TelephonyCommonTests/AndroidManifest.xml
new file mode 100644
index 0000000..63f38c6
--- /dev/null
+++ b/tests/TelephonyCommonTests/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.internal.telephony.tests"
+          android:debuggable="true">
+
+    <application android:label="TelephonyCommonTests"
+                 android:debuggable="true">
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.internal.telephony.tests"
+                     android:label="Telephony common tests"
+                     android:debuggable="true"/>
+</manifest>
diff --git a/tests/TelephonyCommonTests/AndroidTest.xml b/tests/TelephonyCommonTests/AndroidTest.xml
new file mode 100644
index 0000000..e9fdabc
--- /dev/null
+++ b/tests/TelephonyCommonTests/AndroidTest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+<configuration description="Runs Telephony Common Test Cases.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-instrumentation" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="TelephonyCommonTests.apk" />
+    </target_preparer>
+
+    <option name="test-tag" value="TelephonyCommonTests" />
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="com.android.internal.telephony.tests" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+    </test>
+</configuration>
diff --git a/tests/TelephonyCommonTests/jarjar-rules.txt b/tests/TelephonyCommonTests/jarjar-rules.txt
new file mode 100644
index 0000000..fe34719
--- /dev/null
+++ b/tests/TelephonyCommonTests/jarjar-rules.txt
@@ -0,0 +1 @@
+rule com.android.internal.telephony.SmsApplication* com.android.internal.telephony.tests.SmsApplication@1
diff --git a/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java b/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java
new file mode 100644
index 0000000..6d0ee18
--- /dev/null
+++ b/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java
@@ -0,0 +1,238 @@
+/*
+ * 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 com.android.internal.telephony.tests;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.Manifest;
+import android.app.AppOpsManager;
+import android.app.role.RoleManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.os.UserHandle;
+import android.provider.Telephony;
+import android.telephony.TelephonyManager;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.internal.telephony.SmsApplication;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Unit tests for the {@link SmsApplication} utility class
+ */
+@RunWith(AndroidJUnit4.class)
+public class SmsApplicationTest {
+    private static final ComponentName TEST_COMPONENT_NAME =
+            ComponentName.unflattenFromString("com.android.test/.TestSmsApp");
+    private static final String MMS_RECEIVER_NAME = "TestMmsReceiver";
+    private static final String RESPOND_VIA_SMS_NAME = "TestRespondViaSmsHandler";
+    private static final String SEND_TO_NAME = "TestSendTo";
+    private static final int SMS_APP_UID = 10001;
+
+    private static final int FAKE_PHONE_UID = 10002;
+    private static final int FAKE_MMS_UID = 10003;
+    private static final int FAKE_BT_UID = 10004;
+    private static final int FAKE_TELEPHONY_PROVIDER_UID = 10005;
+
+    private static final String[] APP_OPS_TO_CHECK = {
+            AppOpsManager.OPSTR_READ_SMS,
+            AppOpsManager.OPSTR_WRITE_SMS,
+            AppOpsManager.OPSTR_RECEIVE_SMS,
+            AppOpsManager.OPSTR_RECEIVE_WAP_PUSH,
+            AppOpsManager.OPSTR_SEND_SMS,
+            AppOpsManager.OPSTR_READ_CELL_BROADCASTS
+    };
+
+    @Mock private Context mContext;
+    @Mock private TelephonyManager mTelephonyManager;
+    @Mock private RoleManager mRoleManager;
+    @Mock private PackageManager mPackageManager;
+    @Mock private AppOpsManager mAppOpsManager;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
+        when(mContext.getSystemService(Context.ROLE_SERVICE)).thenReturn(mRoleManager);
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
+        when(mContext.getSystemService(RoleManager.class)).thenReturn(mRoleManager);
+        when(mContext.getSystemService(AppOpsManager.class)).thenReturn(mAppOpsManager);
+
+        doAnswer(invocation -> getResolveInfosForIntent(invocation.getArgument(0)))
+                .when(mPackageManager)
+                .queryBroadcastReceiversAsUser(nullable(Intent.class), anyInt(), anyInt());
+        doAnswer(invocation -> getResolveInfosForIntent(invocation.getArgument(0)))
+                .when(mPackageManager)
+                .queryIntentActivitiesAsUser(nullable(Intent.class), anyInt(), anyInt());
+        doAnswer(invocation -> getResolveInfosForIntent(invocation.getArgument(0)))
+                .when(mPackageManager)
+                .queryIntentServicesAsUser(nullable(Intent.class), anyInt(),
+                        nullable(UserHandle.class));
+
+        when(mTelephonyManager.isSmsCapable()).thenReturn(true);
+        when(mRoleManager.isRoleAvailable(RoleManager.ROLE_SMS)).thenReturn(true);
+        when(mRoleManager.getDefaultSmsPackage(anyInt()))
+                .thenReturn(TEST_COMPONENT_NAME.getPackageName());
+
+        for (String opStr : APP_OPS_TO_CHECK) {
+            when(mAppOpsManager.unsafeCheckOp(
+                    opStr, SMS_APP_UID, TEST_COMPONENT_NAME.getPackageName()))
+                    .thenReturn(AppOpsManager.MODE_ALLOWED);
+        }
+    }
+
+    @Test
+    public void testGetDefaultSmsApplication() {
+        assertEquals(TEST_COMPONENT_NAME,
+                SmsApplication.getDefaultSmsApplicationAsUser(mContext, false, 0));
+    }
+
+    @Test
+    public void testGetDefaultSmsApplicationWithAppOpsFix() throws Exception {
+        when(mAppOpsManager.unsafeCheckOp(AppOpsManager.OPSTR_READ_SMS, SMS_APP_UID,
+                TEST_COMPONENT_NAME.getPackageName()))
+                .thenReturn(AppOpsManager.MODE_IGNORED);
+        setupPackageInfosForCoreApps();
+
+        assertEquals(TEST_COMPONENT_NAME,
+                SmsApplication.getDefaultSmsApplicationAsUser(mContext, true, 0));
+        verify(mAppOpsManager, atLeastOnce()).setUidMode(AppOpsManager.OPSTR_READ_SMS, SMS_APP_UID,
+                AppOpsManager.MODE_ALLOWED);
+    }
+
+    private void setupPackageInfosForCoreApps() throws Exception {
+        PackageInfo phonePackageInfo = new PackageInfo();
+        ApplicationInfo phoneApplicationInfo = new ApplicationInfo();
+        phoneApplicationInfo.uid = FAKE_PHONE_UID;
+        phonePackageInfo.applicationInfo = phoneApplicationInfo;
+        when(mPackageManager.getPackageInfo(eq(SmsApplication.PHONE_PACKAGE_NAME), anyInt()))
+                .thenReturn(phonePackageInfo);
+
+        PackageInfo mmsPackageInfo = new PackageInfo();
+        ApplicationInfo mmsApplicationInfo = new ApplicationInfo();
+        mmsApplicationInfo.uid = FAKE_MMS_UID;
+        mmsPackageInfo.applicationInfo = mmsApplicationInfo;
+        when(mPackageManager.getPackageInfo(eq(SmsApplication.MMS_SERVICE_PACKAGE_NAME), anyInt()))
+                .thenReturn(mmsPackageInfo);
+
+        PackageInfo bluetoothPackageInfo = new PackageInfo();
+        ApplicationInfo bluetoothApplicationInfo = new ApplicationInfo();
+        bluetoothApplicationInfo.uid = FAKE_BT_UID;
+        bluetoothPackageInfo.applicationInfo = bluetoothApplicationInfo;
+        when(mPackageManager.getPackageInfo(eq(SmsApplication.BLUETOOTH_PACKAGE_NAME), anyInt()))
+                .thenReturn(bluetoothPackageInfo);
+
+        PackageInfo telephonyProviderPackageInfo = new PackageInfo();
+        ApplicationInfo telephonyProviderApplicationInfo = new ApplicationInfo();
+        telephonyProviderApplicationInfo.uid = FAKE_TELEPHONY_PROVIDER_UID;
+        telephonyProviderPackageInfo.applicationInfo = telephonyProviderApplicationInfo;
+        when(mPackageManager.getPackageInfo(
+                eq(SmsApplication.TELEPHONY_PROVIDER_PACKAGE_NAME), anyInt()))
+                .thenReturn(telephonyProviderPackageInfo);
+    }
+
+    private List<ResolveInfo> getResolveInfosForIntent(Intent intent) {
+        switch (intent.getAction()) {
+            case Telephony.Sms.Intents.SMS_DELIVER_ACTION:
+                return Collections.singletonList(makeSmsDeliverResolveInfo());
+            case Telephony.Sms.Intents.WAP_PUSH_DELIVER_ACTION:
+                return Collections.singletonList(makeWapPushResolveInfo());
+            case TelephonyManager.ACTION_RESPOND_VIA_MESSAGE:
+                return Collections.singletonList(makeRespondViaMessageResolveInfo());
+            case Intent.ACTION_SENDTO:
+                return Collections.singletonList(makeSendToResolveInfo());
+        }
+        return Collections.emptyList();
+    }
+
+    private ApplicationInfo makeSmsApplicationInfo() {
+        ApplicationInfo applicationInfo = new ApplicationInfo();
+        applicationInfo.uid = SMS_APP_UID;
+        return applicationInfo;
+    }
+
+    private ResolveInfo makeSmsDeliverResolveInfo() {
+        ResolveInfo info = new ResolveInfo();
+        ActivityInfo activityInfo = new ActivityInfo();
+        activityInfo.applicationInfo = makeSmsApplicationInfo();
+
+        activityInfo.permission = Manifest.permission.BROADCAST_SMS;
+        activityInfo.packageName = TEST_COMPONENT_NAME.getPackageName();
+        activityInfo.name = TEST_COMPONENT_NAME.getClassName();
+
+        info.activityInfo = activityInfo;
+        return info;
+    }
+
+    private ResolveInfo makeWapPushResolveInfo() {
+        ResolveInfo info = new ResolveInfo();
+        ActivityInfo activityInfo = new ActivityInfo();
+
+        activityInfo.permission = Manifest.permission.BROADCAST_WAP_PUSH;
+        activityInfo.packageName = TEST_COMPONENT_NAME.getPackageName();
+        activityInfo.name = MMS_RECEIVER_NAME;
+
+        info.activityInfo = activityInfo;
+        return info;
+    }
+
+    private ResolveInfo makeRespondViaMessageResolveInfo() {
+        ResolveInfo info = new ResolveInfo();
+        ServiceInfo serviceInfo = new ServiceInfo();
+
+        serviceInfo.permission = Manifest.permission.SEND_RESPOND_VIA_MESSAGE;
+        serviceInfo.packageName = TEST_COMPONENT_NAME.getPackageName();
+        serviceInfo.name = RESPOND_VIA_SMS_NAME;
+
+        info.serviceInfo = serviceInfo;
+        return info;
+    }
+
+    private ResolveInfo makeSendToResolveInfo() {
+        ResolveInfo info = new ResolveInfo();
+        ActivityInfo activityInfo = new ActivityInfo();
+
+        activityInfo.packageName = TEST_COMPONENT_NAME.getPackageName();
+        activityInfo.name = SEND_TO_NAME;
+
+        info.activityInfo = activityInfo;
+        return info;
+    }
+}
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 2a165d3..e9f7a46 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -2428,7 +2428,8 @@
         } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)
                 || allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
             key = SSID + KeyMgmt.strings[KeyMgmt.WPA_EAP];
-        } else if (wepKeys[0] != null) {
+        } else if (wepTxKeyIndex >= 0 && wepTxKeyIndex < wepKeys.length
+                && wepKeys[wepTxKeyIndex] != null) {
             key = SSID + "WEP";
         } else if (allowedKeyManagement.get(KeyMgmt.OWE)) {
             key = SSID + KeyMgmt.strings[KeyMgmt.OWE];
@@ -2590,9 +2591,8 @@
         return mPasspointManagementObjectTree;
     }
 
-    /** copy constructor {@hide} */
-    @UnsupportedAppUsage
-    public WifiConfiguration(WifiConfiguration source) {
+    /** Copy constructor */
+    public WifiConfiguration(@NonNull WifiConfiguration source) {
         if (source != null) {
             networkId = source.networkId;
             status = source.status;
diff --git a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
index 5d6549e..909cfef 100644
--- a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
@@ -270,7 +270,23 @@
         config.allowedKeyManagement.clear();
         assertEquals(mSsid + "WEP", config.getSsidAndSecurityTypeString());
 
+        // set WEP key and give a valid index.
         config.wepKeys[0] = null;
+        config.wepKeys[2] = "TestWep";
+        config.wepTxKeyIndex = 2;
+        config.allowedKeyManagement.clear();
+        assertEquals(mSsid + "WEP", config.getSsidAndSecurityTypeString());
+
+        // set WEP key but does not give a valid index.
+        config.wepKeys[0] = null;
+        config.wepKeys[2] = "TestWep";
+        config.wepTxKeyIndex = 0;
+        config.allowedKeyManagement.clear();
+        config.allowedKeyManagement.set(KeyMgmt.OWE);
+        assertEquals(mSsid + KeyMgmt.strings[KeyMgmt.OWE], config.getSsidAndSecurityTypeString());
+
+        config.wepKeys[0] = null;
+        config.wepTxKeyIndex = 0;
         config.allowedKeyManagement.clear();
         config.allowedKeyManagement.set(KeyMgmt.OWE);
         assertEquals(mSsid + KeyMgmt.strings[KeyMgmt.OWE], config.getSsidAndSecurityTypeString());