Merge "idmap2: fix clang-tidy warnings [misc-*]"
diff --git a/api/current.txt b/api/current.txt
index d881857..3d57a42 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -23379,12 +23379,13 @@
     method public android.media.AudioPresentation.Builder setProgramId(int);
   }
 
-  public class AudioRecord implements android.media.AudioRouting {
+  public class AudioRecord implements android.media.AudioRecordingMonitor android.media.AudioRouting {
     ctor public AudioRecord(int, int, int, int, int) throws java.lang.IllegalArgumentException;
     method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
     method public deprecated void addOnRoutingChangedListener(android.media.AudioRecord.OnRoutingChangedListener, android.os.Handler);
     method protected void finalize();
     method public java.util.List<android.media.MicrophoneInfo> getActiveMicrophones() throws java.io.IOException;
+    method public android.media.AudioRecordingConfiguration getActiveRecordingConfiguration();
     method public int getAudioFormat();
     method public int getAudioSessionId();
     method public int getAudioSource();
@@ -23409,6 +23410,7 @@
     method public int read(float[], int, int, int);
     method public int read(java.nio.ByteBuffer, int);
     method public int read(java.nio.ByteBuffer, int, int);
+    method public void registerAudioRecordingCallback(java.util.concurrent.Executor, android.media.AudioManager.AudioRecordingCallback);
     method public void release();
     method public void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener);
     method public deprecated void removeOnRoutingChangedListener(android.media.AudioRecord.OnRoutingChangedListener);
@@ -23420,6 +23422,7 @@
     method public void startRecording() throws java.lang.IllegalStateException;
     method public void startRecording(android.media.MediaSyncEvent) throws java.lang.IllegalStateException;
     method public void stop() throws java.lang.IllegalStateException;
+    method public void unregisterAudioRecordingCallback(android.media.AudioManager.AudioRecordingCallback);
     field public static final int ERROR = -1; // 0xffffffff
     field public static final int ERROR_BAD_VALUE = -2; // 0xfffffffe
     field public static final int ERROR_DEAD_OBJECT = -6; // 0xfffffffa
@@ -23474,6 +23477,12 @@
     field public static final android.os.Parcelable.Creator<android.media.AudioRecordingConfiguration> CREATOR;
   }
 
+  public abstract interface AudioRecordingMonitor {
+    method public abstract android.media.AudioRecordingConfiguration getActiveRecordingConfiguration();
+    method public abstract void registerAudioRecordingCallback(java.util.concurrent.Executor, android.media.AudioManager.AudioRecordingCallback);
+    method public abstract void unregisterAudioRecordingCallback(android.media.AudioManager.AudioRecordingCallback);
+  }
+
   public abstract interface AudioRouting {
     method public abstract void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
     method public abstract android.media.AudioDeviceInfo getPreferredDevice();
@@ -25475,11 +25484,12 @@
     field public static final int MEDIA_TRACK_TYPE_VIDEO = 1; // 0x1
   }
 
-  public class MediaRecorder implements android.media.AudioRouting {
+  public class MediaRecorder implements android.media.AudioRecordingMonitor android.media.AudioRouting {
     ctor public MediaRecorder();
     method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
     method protected void finalize();
     method public java.util.List<android.media.MicrophoneInfo> getActiveMicrophones() throws java.io.IOException;
+    method public android.media.AudioRecordingConfiguration getActiveRecordingConfiguration();
     method public static final int getAudioSourceMax();
     method public int getMaxAmplitude() throws java.lang.IllegalStateException;
     method public android.os.PersistableBundle getMetrics();
@@ -25488,6 +25498,7 @@
     method public android.view.Surface getSurface();
     method public void pause() throws java.lang.IllegalStateException;
     method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
+    method public void registerAudioRecordingCallback(java.util.concurrent.Executor, android.media.AudioManager.AudioRecordingCallback);
     method public void release();
     method public void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener);
     method public void reset();
@@ -25523,6 +25534,7 @@
     method public void setVideoSource(int) throws java.lang.IllegalStateException;
     method public void start() throws java.lang.IllegalStateException;
     method public void stop() throws java.lang.IllegalStateException;
+    method public void unregisterAudioRecordingCallback(android.media.AudioManager.AudioRecordingCallback);
     field public static final int MEDIA_ERROR_SERVER_DIED = 100; // 0x64
     field public static final int MEDIA_RECORDER_ERROR_UNKNOWN = 1; // 0x1
     field public static final int MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800; // 0x320
@@ -38682,22 +38694,23 @@
     field public static final android.net.Uri CONTENT_URI;
     field public static final java.lang.String CURRENT = "current";
     field public static final java.lang.String DEFAULT_SORT_ORDER = "name ASC";
-    field public static final java.lang.String MCC = "mcc";
+    field public static final deprecated java.lang.String MCC = "mcc";
     field public static final java.lang.String MMSC = "mmsc";
     field public static final java.lang.String MMSPORT = "mmsport";
     field public static final java.lang.String MMSPROXY = "mmsproxy";
-    field public static final java.lang.String MNC = "mnc";
-    field public static final java.lang.String MVNO_MATCH_DATA = "mvno_match_data";
-    field public static final java.lang.String MVNO_TYPE = "mvno_type";
+    field public static final deprecated java.lang.String MNC = "mnc";
+    field public static final deprecated java.lang.String MVNO_MATCH_DATA = "mvno_match_data";
+    field public static final deprecated java.lang.String MVNO_TYPE = "mvno_type";
     field public static final java.lang.String NAME = "name";
     field public static final java.lang.String NETWORK_TYPE_BITMASK = "network_type_bitmask";
-    field public static final java.lang.String NUMERIC = "numeric";
+    field public static final deprecated java.lang.String NUMERIC = "numeric";
     field public static final java.lang.String PASSWORD = "password";
     field public static final java.lang.String PORT = "port";
     field public static final java.lang.String PROTOCOL = "protocol";
     field public static final java.lang.String PROXY = "proxy";
     field public static final java.lang.String ROAMING_PROTOCOL = "roaming_protocol";
     field public static final java.lang.String SERVER = "server";
+    field public static final android.net.Uri SIM_APN_URI;
     field public static final java.lang.String SUBSCRIPTION_ID = "sub_id";
     field public static final java.lang.String TYPE = "type";
     field public static final java.lang.String USER = "user";
diff --git a/api/system-current.txt b/api/system-current.txt
index 0a42d25..3aa7cc7 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -2953,7 +2953,7 @@
     field public static final int PLAYER_TYPE_UNKNOWN = -1; // 0xffffffff
   }
 
-  public class AudioRecord implements android.media.AudioRouting {
+  public class AudioRecord implements android.media.AudioRecordingMonitor android.media.AudioRouting {
     ctor public AudioRecord(android.media.AudioAttributes, android.media.AudioFormat, int, int) throws java.lang.IllegalArgumentException;
   }
 
@@ -6481,12 +6481,17 @@
     method public void getDownloadableSubscriptionMetadata(android.telephony.euicc.DownloadableSubscription, android.app.PendingIntent);
     method public int getOtaStatus();
     field public static final java.lang.String ACTION_OTA_STATUS_CHANGED = "android.telephony.euicc.action.OTA_STATUS_CHANGED";
+    field public static final java.lang.String ACTION_PROFILE_SELECTION = "android.telephony.euicc.action.PROFILE_SELECTION";
     field public static final java.lang.String ACTION_PROVISION_EMBEDDED_SUBSCRIPTION = "android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION";
+    field public static final int EUICC_ACTIVATION_TYPE_BACKUP = 2; // 0x2
+    field public static final int EUICC_ACTIVATION_TYPE_DEFAULT = 1; // 0x1
+    field public static final int EUICC_ACTIVATION_TYPE_TRANSFER = 3; // 0x3
     field public static final int EUICC_OTA_FAILED = 2; // 0x2
     field public static final int EUICC_OTA_IN_PROGRESS = 1; // 0x1
     field public static final int EUICC_OTA_NOT_NEEDED = 4; // 0x4
     field public static final int EUICC_OTA_STATUS_UNAVAILABLE = 5; // 0x5
     field public static final int EUICC_OTA_SUCCEEDED = 3; // 0x3
+    field public static final java.lang.String EXTRA_ACTIVATION_TYPE = "android.telephony.euicc.extra.ACTIVATION_TYPE";
     field public static final java.lang.String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS";
     field public static final java.lang.String EXTRA_FORCE_PROVISION = "android.telephony.euicc.extra.FORCE_PROVISION";
   }
diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp
index d7922bc..fe7099b 100644
--- a/cmds/idmap2/Android.bp
+++ b/cmds/idmap2/Android.bp
@@ -12,14 +12,26 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-cc_library {
-    name: "libidmap2",
-    host_supported: true,
+cc_defaults {
+    name: "idmap2_defaults",
     tidy: true,
+    tidy_checks: [
+        "android-*",
+        "misc-*",
+        "modernize-*",
+        "readability-*",
+    ],
     tidy_flags: [
         "-system-headers",
-// b/120024673       "-warnings-as-errors=*",
     ],
+}
+
+cc_library {
+    name: "libidmap2",
+    defaults: [
+        "idmap2_defaults",
+    ],
+    host_supported: true,
     srcs: [
         "libidmap2/BinaryStreamVisitor.cpp",
         "libidmap2/CommandLineOptions.cpp",
@@ -60,12 +72,13 @@
 
 cc_test {
     name: "idmap2_tests",
-    host_supported: true,
-    tidy: true,
-    tidy_flags: [
-        "-system-headers",
-// b/120024673        "-warnings-as-errors=*",
+    defaults: [
+        "idmap2_defaults",
     ],
+    tidy_checks: [
+        "-readability-magic-numbers",
+    ],
+    host_supported: true,
     srcs: [
         "tests/BinaryStreamVisitorTests.cpp",
         "tests/CommandLineOptionsTests.cpp",
@@ -114,12 +127,10 @@
 
 cc_binary {
     name: "idmap2",
-    host_supported: true,
-    tidy: true,
-    tidy_flags: [
-        "-system-headers",
-// b/120024673        "-warnings-as-errors=*",
+    defaults: [
+        "idmap2_defaults",
     ],
+    host_supported: true,
     srcs: [
         "idmap2/Create.cpp",
         "idmap2/Dump.cpp",
@@ -156,19 +167,11 @@
 
 cc_binary {
     name: "idmap2d",
+    defaults: [
+        "idmap2_defaults",
+    ],
     host_supported: false,
-    tidy: true,
-    tidy_checks: [
-        // remove google-default-arguments or clang-tidy will complain about
-        // the auto-generated file IIdmap2.cpp
-        "-google-default-arguments",
-    ],
-    tidy_flags: [
-        "-system-headers",
-// b/120024673        "-warnings-as-errors=*",
-    ],
     srcs: [
-        ":idmap2_aidl",
         "idmap2d/Idmap2Service.cpp",
         "idmap2d/Main.cpp",
     ],
@@ -181,9 +184,30 @@
         "libutils",
         "libziparchive",
     ],
+    static_libs: [
+        "libidmap2daidl",
+    ],
     init_rc: ["idmap2d/idmap2d.rc"],
 }
 
+cc_library_static {
+    name: "libidmap2daidl",
+    defaults: [
+        "idmap2_defaults",
+    ],
+    tidy: false,
+    host_supported: false,
+    srcs: [
+        ":idmap2_aidl",
+    ],
+    shared_libs: [
+        "libbase",
+    ],
+    aidl: {
+        export_aidl_headers: true,
+    },
+}
+
 filegroup {
     name: "idmap2_aidl",
     srcs: [
diff --git a/cmds/idmap2/idmap2/Main.cpp b/cmds/idmap2/idmap2/Main.cpp
index 5d9ea77..5e71251 100644
--- a/cmds/idmap2/idmap2/Main.cpp
+++ b/cmds/idmap2/idmap2/Main.cpp
@@ -32,7 +32,9 @@
 typedef std::map<std::string, std::function<int(const std::vector<std::string>&, std::ostream&)>>
     NameToFunctionMap;
 
-static void PrintUsage(const NameToFunctionMap& commands, std::ostream& out) {
+namespace {
+
+void PrintUsage(const NameToFunctionMap& commands, std::ostream& out) {
   out << "usage: idmap2 [";
   for (auto iter = commands.cbegin(); iter != commands.cend(); iter++) {
     if (iter != commands.cbegin()) {
@@ -43,6 +45,8 @@
   out << "]" << std::endl;
 }
 
+}  // namespace
+
 int main(int argc, char** argv) {
   const NameToFunctionMap commands = {
       {"create", Create}, {"dump", Dump}, {"lookup", Lookup}, {"scan", Scan}, {"verify", Verify},
diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp
index 49bb7d8..89aa6d8 100644
--- a/cmds/idmap2/libidmap2/Idmap.cpp
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -39,6 +39,8 @@
 namespace android {
 namespace idmap2 {
 
+namespace {
+
 #define EXTRACT_TYPE(resid) ((0x00ff0000 & (resid)) >> 16)
 
 #define EXTRACT_ENTRY(resid) (0x0000ffff & (resid))
@@ -62,7 +64,7 @@
   std::map<TypeId, std::set<std::pair<ResourceId, ResourceId>>> map_;
 };
 
-static bool WARN_UNUSED Read16(std::istream& stream, uint16_t* out) {
+bool WARN_UNUSED Read16(std::istream& stream, uint16_t* out) {
   uint16_t value;
   if (stream.read(reinterpret_cast<char*>(&value), sizeof(uint16_t))) {
     *out = dtohl(value);
@@ -71,7 +73,7 @@
   return false;
 }
 
-static bool WARN_UNUSED Read32(std::istream& stream, uint32_t* out) {
+bool WARN_UNUSED Read32(std::istream& stream, uint32_t* out) {
   uint32_t value;
   if (stream.read(reinterpret_cast<char*>(&value), sizeof(uint32_t))) {
     *out = dtohl(value);
@@ -81,7 +83,7 @@
 }
 
 // a string is encoded as a kIdmapStringLength char array; the array is always null-terminated
-static bool WARN_UNUSED ReadString(std::istream& stream, char out[kIdmapStringLength]) {
+bool WARN_UNUSED ReadString(std::istream& stream, char out[kIdmapStringLength]) {
   char buf[kIdmapStringLength];
   memset(buf, 0, sizeof(buf));
   if (!stream.read(buf, sizeof(buf))) {
@@ -94,7 +96,7 @@
   return true;
 }
 
-static ResourceId NameToResid(const AssetManager2& am, const std::string& name) {
+ResourceId NameToResid(const AssetManager2& am, const std::string& name) {
   return am.GetResourceId(name);
 }
 
@@ -107,7 +109,7 @@
 // relying on a hard-coded index. This however requires storing the package name in the idmap
 // header, which in turn requires incrementing the idmap version. Because the initial version of
 // idmap2 is compatible with idmap, this will have to wait for now.
-static const LoadedPackage* GetPackageAtIndex0(const LoadedArsc& loaded_arsc) {
+const LoadedPackage* GetPackageAtIndex0(const LoadedArsc& loaded_arsc) {
   const std::vector<std::unique_ptr<const LoadedPackage>>& packages = loaded_arsc.GetPackages();
   if (packages.empty()) {
     return nullptr;
@@ -116,6 +118,8 @@
   return loaded_arsc.GetPackageById(id);
 }
 
+}  // namespace
+
 std::unique_ptr<const IdmapHeader> IdmapHeader::FromBinaryStream(std::istream& stream) {
   std::unique_ptr<IdmapHeader> idmap_header(new IdmapHeader());
 
diff --git a/cmds/idmap2/tests/Idmap2BinaryTests.cpp b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
index 5c4e857..cfe5361 100644
--- a/cmds/idmap2/tests/Idmap2BinaryTests.cpp
+++ b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
@@ -51,8 +51,10 @@
 
 class Idmap2BinaryTests : public Idmap2Tests {};
 
-static void AssertIdmap(const Idmap& idmap, const std::string& target_apk_path,
-                        const std::string& overlay_apk_path) {
+namespace {
+
+void AssertIdmap(const Idmap& idmap, const std::string& target_apk_path,
+                 const std::string& overlay_apk_path) {
   // check that the idmap file looks reasonable (IdmapTests is responsible for
   // more in-depth verification)
   ASSERT_EQ(idmap.GetHeader()->GetMagic(), kIdmapMagic);
@@ -67,6 +69,8 @@
     ASSERT_NO_FATAL_FAILURE(AssertIdmap(idmap_ref, target_apk_path, overlay_apk_path)); \
   } while (0)
 
+}  // namespace
+
 TEST_F(Idmap2BinaryTests, Create) {
   // clang-format off
   auto result = ExecuteBinary({"idmap2",
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index c850a4e..dd0242a 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -19,7 +19,7 @@
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
 import android.annotation.IntDef;
-import android.annotation.Nullable;
+import android.annotation.NonNull;
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
@@ -179,13 +179,13 @@
      * @param isExpanded whether the notification is expanded.
      */
     public void onNotificationExpansionChanged(
-            String key, boolean isUserAction, boolean isExpanded) {}
+            @NonNull String key, boolean isUserAction, boolean isExpanded) {}
 
     /**
      * Implement this to know when a direct reply is sent from a notification.
      * @param key the notification key
      */
-    public void onNotificationDirectReply(String key) {}
+    public void onNotificationDirectReply(@NonNull String key) {}
 
     /**
      * Implement this to know when a suggested reply is sent.
@@ -193,7 +193,9 @@
      * @param reply the reply that is just sent
      * @param source the source that provided the reply, e.g. SOURCE_FROM_APP
      */
-    public void onSuggestedReplySent(String key, CharSequence reply, @Source int source) {}
+    public void onSuggestedReplySent(@NonNull String key, @NonNull CharSequence reply,
+            @Source int source) {
+    }
 
     /**
      * Implement this to know when an action is clicked.
@@ -201,7 +203,8 @@
      * @param action the action that is just clicked
      * @param source the source that provided the action, e.g. SOURCE_FROM_APP
      */
-    public void onActionClicked(String key, @Nullable Notification.Action action, int source) {
+    public void onActionClicked(@NonNull String key, @NonNull Notification.Action action,
+            @Source int source) {
     }
 
     /**
diff --git a/core/java/android/view/textclassifier/ActionsSuggestionsHelper.java b/core/java/android/view/textclassifier/ActionsSuggestionsHelper.java
index b41096c..77cb4cd 100644
--- a/core/java/android/view/textclassifier/ActionsSuggestionsHelper.java
+++ b/core/java/android/view/textclassifier/ActionsSuggestionsHelper.java
@@ -17,6 +17,7 @@
 package android.view.textclassifier;
 
 import android.app.Person;
+import android.content.Context;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 
@@ -28,7 +29,10 @@
 import java.util.ArrayList;
 import java.util.Deque;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
+import java.util.Objects;
+import java.util.StringJoiner;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
@@ -84,6 +88,29 @@
                 new ActionsSuggestionsModel.ConversationMessage[nativeMessages.size()]);
     }
 
+    /**
+     * Returns the result id for logging.
+     */
+    public static String createResultId(
+            Context context,
+            List<ConversationActions.Message> messages,
+            int modelVersion,
+            List<Locale> modelLocales) {
+        final StringJoiner localesJoiner = new StringJoiner(",");
+        for (Locale locale : modelLocales) {
+            localesJoiner.add(locale.toLanguageTag());
+        }
+        final String modelName = String.format(
+                Locale.US, "%s_v%d", localesJoiner.toString(), modelVersion);
+        final int hash = Objects.hash(
+                messages.stream()
+                        .map(ConversationActions.Message::getText)
+                        .collect(Collectors.toList()),
+                context.getPackageName());
+        return SelectionSessionLogger.SignatureParser.createSignature(
+                SelectionSessionLogger.CLASSIFIER_ID, modelName, hash);
+    }
+
     private static final class PersonEncoder {
         private final Map<Person, Integer> mMapping = new ArrayMap<>();
         private int mNextUserId = FIRST_NON_LOCAL_USER;
diff --git a/core/java/android/view/textclassifier/TextClassifierEvent.java b/core/java/android/view/textclassifier/TextClassifierEvent.java
index 3bb9ee8..f2fea02 100644
--- a/core/java/android/view/textclassifier/TextClassifierEvent.java
+++ b/core/java/android/view/textclassifier/TextClassifierEvent.java
@@ -27,6 +27,7 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
 
 /**
  * A text classifier event.
@@ -498,4 +499,25 @@
         }
         // TODO: Add build(boolean validate).
     }
+
+    @Override
+    public String toString() {
+        StringBuilder out = new StringBuilder(128);
+        out.append("TextClassifierEvent{");
+        out.append("mEventCategory=").append(mEventCategory);
+        out.append(", mEventType=").append(mEventType);
+        out.append(", mEventContext=").append(mEventContext);
+        out.append(", mResultId=").append(mResultId);
+        out.append(", mEventIndex=").append(mEventIndex);
+        out.append(", mEventTime=").append(mEventTime);
+        out.append(", mExtras=").append(mExtras);
+        out.append(", mRelativeWordStartIndex=").append(mRelativeWordStartIndex);
+        out.append(", mRelativeWordEndIndex=").append(mRelativeWordEndIndex);
+        out.append(", mRelativeSuggestedWordStartIndex=").append(mRelativeSuggestedWordStartIndex);
+        out.append(", mRelativeSuggestedWordEndIndex=").append(mRelativeSuggestedWordEndIndex);
+        out.append(", mActionIndices=").append(Arrays.toString(mActionIndices));
+        out.append(", mLanguage=").append(mLanguage);
+        out.append("}");
+        return out.toString();
+    }
 }
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 9b0f9c6..fcd06c3 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -80,6 +80,8 @@
 
     private static final String LOG_TAG = DEFAULT_LOG_TAG;
 
+    private static final boolean DEBUG = false;
+
     private static final File FACTORY_MODEL_DIR = new File("/etc/textclassifier/");
     // Annotator
     private static final String ANNOTATOR_FACTORY_MODEL_FILENAME_REGEX =
@@ -109,6 +111,8 @@
     @GuardedBy("mLock") // Do not access outside this lock.
     private LangIdModel mLangIdImpl;
     @GuardedBy("mLock") // Do not access outside this lock.
+    private ModelFileManager.ModelFile mActionModelInUse;
+    @GuardedBy("mLock") // Do not access outside this lock.
     private ActionsSuggestionsModel mActionsImpl;
 
     private final Object mLoggerLock = new Object();
@@ -342,8 +346,10 @@
     }
 
     @Override
-    public void onTextClassifierEvent(@NonNull TextClassifierEvent event) {
-        // TODO: Implement.
+    public void onTextClassifierEvent(TextClassifierEvent event) {
+        if (DEBUG) {
+            Log.d(DEFAULT_LOG_TAG, "onTextClassifierEvent() called with: event = [" + event + "]");
+        }
     }
 
     /** @inheritDoc */
@@ -408,7 +414,12 @@
                                 .setConfidenceScore(nativeSuggestion.getScore())
                                 .build());
             }
-            return new ConversationActions(conversationActions, /*id*/ null);
+            String resultId = ActionsSuggestionsHelper.createResultId(
+                    mContext,
+                    request.getConversation(),
+                    mActionModelInUse.getVersion(),
+                    mActionModelInUse.getSupportedLocales());
+            return new ConversationActions(conversationActions, resultId);
         } catch (Throwable t) {
             // Avoid throwing from this method. Log the error.
             Log.e(LOG_TAG, "Error suggesting conversation actions.", t);
@@ -517,6 +528,7 @@
                 try {
                     if (pfd != null) {
                         mActionsImpl = new ActionsSuggestionsModel(pfd.getFd());
+                        mActionModelInUse = bestModel;
                     }
                 } finally {
                     maybeCloseAndLogError(pfd);
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 12ca78a..eb7338a 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -45,7 +45,7 @@
 
 class BitmapWrapper {
 public:
-    BitmapWrapper(Bitmap* bitmap)
+    explicit BitmapWrapper(Bitmap* bitmap)
         : mBitmap(bitmap) { }
 
     void freePixels() {
diff --git a/core/jni/android/graphics/FontUtils.h b/core/jni/android/graphics/FontUtils.h
index 9f6462e..b36b4e6 100644
--- a/core/jni/android/graphics/FontUtils.h
+++ b/core/jni/android/graphics/FontUtils.h
@@ -29,7 +29,7 @@
 namespace android {
 
 struct FontFamilyWrapper {
-  FontFamilyWrapper(std::shared_ptr<minikin::FontFamily>&& family) : family(family) {}
+  explicit FontFamilyWrapper(std::shared_ptr<minikin::FontFamily>&& family) : family(family) {}
   std::shared_ptr<minikin::FontFamily> family;
 };
 
diff --git a/core/jni/android/graphics/GIFMovie.cpp b/core/jni/android/graphics/GIFMovie.cpp
index dd99b37..f84a4bd 100644
--- a/core/jni/android/graphics/GIFMovie.cpp
+++ b/core/jni/android/graphics/GIFMovie.cpp
@@ -21,7 +21,7 @@
 
 class GIFMovie : public Movie {
 public:
-    GIFMovie(SkStream* stream);
+    explicit GIFMovie(SkStream* stream);
     virtual ~GIFMovie();
 
 protected:
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index 33b2689..bd87dcc 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -152,7 +152,7 @@
   const bool is_sock;
 
  private:
-  FileDescriptorInfo(int fd);
+  explicit FileDescriptorInfo(int fd);
 
   FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags,
                      int fd_flags, int fs_flags, off_t offset);
diff --git a/core/jni/fd_utils.h b/core/jni/fd_utils.h
index a3570d7..09022a2 100644
--- a/core/jni/fd_utils.h
+++ b/core/jni/fd_utils.h
@@ -86,7 +86,7 @@
   bool ReopenOrDetach(std::string* error_msg);
 
  private:
-  FileDescriptorTable(const std::unordered_map<int, FileDescriptorInfo*>& map);
+  explicit FileDescriptorTable(const std::unordered_map<int, FileDescriptorInfo*>& map);
 
   bool RestatInternal(std::set<int>& open_fds, std::string* error_msg);
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 8b6f33f..299798b 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4336,7 +4336,7 @@
     <permission android:name="android.permission.SMS_FINANCIAL_TRANSACTIONS"
         android:protectionLevel="signature|appop" />
 
-    <!-- Required for apps targeting {@link android.os.Build.VERSION_CODES#P} that want to use
+    <!-- Required for apps targeting {@link android.os.Build.VERSION_CODES#Q} that want to use
          {@link android.app.Notification.Builder#setFullScreenIntent notification full screen
          intents}.  -->
     <permission android:name="android.permission.USE_FULL_SCREEN_INTENT"
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index c216425..58b57e5 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -33,6 +33,10 @@
         <permission name="android.permission.CRYPT_KEEPER"/>
     </privapp-permissions>
 
+    <privapp-permissions package="com.android.carrierconfig">
+        <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
+    </privapp-permissions>
+
     <privapp-permissions package="com.android.cellbroadcastreceiver">
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
         <permission name="android.permission.MANAGE_USERS"/>
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 6e6ed30..9361c7c 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -55,6 +55,7 @@
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.security.InvalidKeyException;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
@@ -315,13 +316,14 @@
     }
 
     /**
-     * List uids of all keys that are auth bound to the current user. 
+     * List uids of all keys that are auth bound to the current user.
      * Only system is allowed to call this method.
      */
     @UnsupportedAppUsage
     public int[] listUidsOfAuthBoundKeys() {
-        final int MAX_RESULT_SIZE = 100;
-        int[] uidsOut = new int[MAX_RESULT_SIZE];
+        // uids are returned as a list of strings because list of integers
+        // as an output parameter is not supported by aidl-cpp.
+        List<String> uidsOut = new ArrayList<>();
         try {
             int rc = mBinder.listUidsOfAuthBoundKeys(uidsOut);
             if (rc != NO_ERROR) {
@@ -335,8 +337,8 @@
             Log.w(TAG, "KeyStore exception", e);
             return null;
         }
-        // Remove any 0 entries
-        return Arrays.stream(uidsOut).filter(x -> x > 0).toArray();
+        // Turn list of strings into an array of uid integers.
+        return uidsOut.stream().mapToInt(Integer::parseInt).toArray();
    }
 
     public String[] list(String prefix) {
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 4b2353c..33f81f1 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -16,8 +16,10 @@
 
 package android.media;
 
+import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityThread;
@@ -43,6 +45,7 @@
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.concurrent.Executor;
 
 /**
  * The AudioRecord class manages the audio resources for Java applications
@@ -58,7 +61,7 @@
  * been read yet. Data should be read from the audio hardware in chunks of sizes inferior to
  * the total recording buffer size.
  */
-public class AudioRecord implements AudioRouting
+public class AudioRecord implements AudioRouting, AudioRecordingMonitor, AudioRecordingMonitorClient
 {
     //---------------------------------------------------------
     // Constants
@@ -1654,6 +1657,56 @@
         return activeMicrophones;
     }
 
+
+    //--------------------------------------------------------------------------
+    // Implementation of AudioRecordingMonitor interface
+    //--------------------
+
+    AudioRecordingMonitorImpl mRecordingInfoImpl =
+            new AudioRecordingMonitorImpl((AudioRecordingMonitorClient) this);
+
+    /**
+     * Register a callback to be notified of audio capture changes via a
+     * {@link AudioManager.AudioRecordingCallback}. A callback is received when the capture path
+     * configuration changes (pre-processing, format, sampling rate...) or capture is
+     * silenced/unsilenced by the system.
+     * @param executor {@link Executor} to handle the callbacks.
+     * @param cb non-null callback to register
+     */
+    public void registerAudioRecordingCallback(@NonNull @CallbackExecutor Executor executor,
+            @NonNull AudioManager.AudioRecordingCallback cb) {
+        mRecordingInfoImpl.registerAudioRecordingCallback(executor, cb);
+    }
+
+    /**
+     * Unregister an audio recording callback previously registered with
+     * {@link #registerAudioRecordingCallback(Executor, AudioManager.AudioRecordingCallback)}.
+     * @param cb non-null callback to unregister
+     */
+    public void unregisterAudioRecordingCallback(@NonNull AudioManager.AudioRecordingCallback cb) {
+        mRecordingInfoImpl.unregisterAudioRecordingCallback(cb);
+    }
+
+    /**
+     * Returns the current active audio recording for this audio recorder.
+     * @return a valid {@link AudioRecordingConfiguration} if this recorder is active
+     * or null otherwise.
+     * @see AudioRecordingConfiguration
+     */
+    public @Nullable AudioRecordingConfiguration getActiveRecordingConfiguration() {
+        return mRecordingInfoImpl.getActiveRecordingConfiguration();
+    }
+
+    //---------------------------------------------------------
+    // Implementation of AudioRecordingMonitorClient interface
+    //--------------------
+    /**
+     * @hide
+     */
+    public int getPortId() {
+        return native_getPortId();
+    }
+
     //---------------------------------------------------------
     // Interface definitions
     //--------------------
diff --git a/media/java/android/media/AudioRecordingMonitor.java b/media/java/android/media/AudioRecordingMonitor.java
new file mode 100644
index 0000000..e2605d0
--- /dev/null
+++ b/media/java/android/media/AudioRecordingMonitor.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.util.concurrent.Executor;
+
+/**
+ * AudioRecordingMonitor defines an interface implemented by {@link AudioRecord} and
+ * {@link MediaRecorder} allowing applications to install a callback and be notified of changes
+ * in the capture path while recoding is active.
+ */
+public interface AudioRecordingMonitor {
+    /**
+     * Register a callback to be notified of audio capture changes via a
+     * {@link AudioManager.AudioRecordingCallback}. A callback is received when the capture path
+     * configuration changes (pre-processing, format, sampling rate...) or capture is
+     * silenced/unsilenced by the system.
+     * @param executor {@link Executor} to handle the callbacks.
+     * @param cb non-null callback to register
+     */
+    void registerAudioRecordingCallback(@NonNull @CallbackExecutor Executor executor,
+            @NonNull AudioManager.AudioRecordingCallback cb);
+
+    /**
+     * Unregister an audio recording callback previously registered with
+     * {@link #registerAudioRecordingCallback(Executor, AudioManager.AudioRecordingCallback)}.
+     * @param cb non-null callback to unregister
+     */
+    void unregisterAudioRecordingCallback(@NonNull AudioManager.AudioRecordingCallback cb);
+
+    /**
+     * Returns the current active audio recording for this audio recorder.
+     * @return a valid {@link AudioRecordingConfiguration} if this recorder is active
+     * or null otherwise.
+     * @see AudioRecordingConfiguration
+     */
+    @Nullable AudioRecordingConfiguration getActiveRecordingConfiguration();
+}
diff --git a/media/java/android/media/AudioRecordingMonitorClient.java b/media/java/android/media/AudioRecordingMonitorClient.java
new file mode 100644
index 0000000..7578d9b
--- /dev/null
+++ b/media/java/android/media/AudioRecordingMonitorClient.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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;
+
+/**
+ * Interface implemented by classes using { @link AudioRecordingMonitor} interface.
+ * @hide
+ */
+public interface AudioRecordingMonitorClient {
+    /**
+     * @return the unique port ID allocated by audio framework to this recorder
+     */
+    int getPortId();
+}
diff --git a/media/java/android/media/AudioRecordingMonitorImpl.java b/media/java/android/media/AudioRecordingMonitorImpl.java
new file mode 100644
index 0000000..c2cd4bc
--- /dev/null
+++ b/media/java/android/media/AudioRecordingMonitorImpl.java
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.Executor;
+
+/**
+ * Implementation of AudioRecordingMonitor interface.
+ * @hide
+ */
+public class AudioRecordingMonitorImpl implements AudioRecordingMonitor {
+
+    private static final String TAG = "android.media.AudioRecordingMonitor";
+
+    private static IAudioService sService; //lazy initialization, use getService()
+
+    private final AudioRecordingMonitorClient mClient;
+
+    AudioRecordingMonitorImpl(@NonNull AudioRecordingMonitorClient client) {
+        mClient = client;
+    }
+
+    /**
+     * Register a callback to be notified of audio capture changes via a
+     * {@link AudioManager.AudioRecordingCallback}. A callback is received when the capture path
+     * configuration changes (pre-processing, format, sampling rate...) or capture is
+     * silenced/unsilenced by the system.
+     * @param executor {@link Executor} to handle the callbacks.
+     * @param cb non-null callback to register
+     */
+    public void registerAudioRecordingCallback(@NonNull @CallbackExecutor Executor executor,
+            @NonNull AudioManager.AudioRecordingCallback cb) {
+        if (cb == null) {
+            throw new IllegalArgumentException("Illegal null AudioRecordingCallback");
+        }
+        if (executor == null) {
+            throw new IllegalArgumentException("Illegal null Executor");
+        }
+        synchronized (mRecordCallbackLock) {
+            // check if eventCallback already in list
+            for (AudioRecordingCallbackInfo arci : mRecordCallbackList) {
+                if (arci.mCb == cb) {
+                    throw new IllegalArgumentException(
+                            "AudioRecordingCallback already registered");
+                }
+            }
+            beginRecordingCallbackHandling();
+            mRecordCallbackList.add(new AudioRecordingCallbackInfo(executor, cb));
+        }
+    }
+
+    /**
+     * Unregister an audio recording callback previously registered with
+     * {@link #registerAudioRecordingCallback(Executor, AudioManager.AudioRecordingCallback)}.
+     * @param cb non-null callback to unregister
+     */
+    public void unregisterAudioRecordingCallback(@NonNull AudioManager.AudioRecordingCallback cb) {
+        if (cb == null) {
+            throw new IllegalArgumentException("Illegal null AudioRecordingCallback argument");
+        }
+
+        synchronized (mRecordCallbackLock) {
+            for (AudioRecordingCallbackInfo arci : mRecordCallbackList) {
+                if (arci.mCb == cb) {
+                    // ok to remove while iterating over list as we exit iteration
+                    mRecordCallbackList.remove(arci);
+                    if (mRecordCallbackList.size() == 0) {
+                        endRecordingCallbackHandling();
+                    }
+                    return;
+                }
+            }
+            throw new IllegalArgumentException("AudioRecordingCallback was not registered");
+        }
+    }
+
+    /**
+     * Returns the current active audio recording for this audio recorder.
+     * @return a valid {@link AudioRecordingConfiguration} if this recorder is active
+     * or null otherwise.
+     * @see AudioRecordingConfiguration
+     */
+    public @Nullable AudioRecordingConfiguration getActiveRecordingConfiguration() {
+        final IAudioService service = getService();
+        try {
+            List<AudioRecordingConfiguration> configs = service.getActiveRecordingConfigurations();
+            return getMyConfig(configs);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    private static class AudioRecordingCallbackInfo {
+        final AudioManager.AudioRecordingCallback mCb;
+        final Executor mExecutor;
+        AudioRecordingCallbackInfo(Executor e, AudioManager.AudioRecordingCallback cb) {
+            mExecutor = e;
+            mCb = cb;
+        }
+    }
+
+    private static final int MSG_RECORDING_CONFIG_CHANGE = 1;
+
+    private final Object mRecordCallbackLock = new Object();
+    @GuardedBy("mRecordCallbackLock")
+    @NonNull private LinkedList<AudioRecordingCallbackInfo> mRecordCallbackList =
+            new LinkedList<AudioRecordingCallbackInfo>();
+    @GuardedBy("mRecordCallbackLock")
+    private @Nullable HandlerThread mRecordingCallbackHandlerThread;
+    @GuardedBy("mRecordCallbackLock")
+    private @Nullable volatile Handler mRecordingCallbackHandler;
+
+    @GuardedBy("mRecordCallbackLock")
+    private final IRecordingConfigDispatcher mRecordingCallback =
+            new IRecordingConfigDispatcher.Stub() {
+        @Override
+        public void dispatchRecordingConfigChange(List<AudioRecordingConfiguration> configs) {
+            AudioRecordingConfiguration config = getMyConfig(configs);
+            if (config != null) {
+                synchronized (mRecordCallbackLock) {
+                    if (mRecordingCallbackHandler != null) {
+                        final Message m = mRecordingCallbackHandler.obtainMessage(
+                                              MSG_RECORDING_CONFIG_CHANGE/*what*/, config /*obj*/);
+                        mRecordingCallbackHandler.sendMessage(m);
+                    }
+                }
+            }
+        }
+    };
+
+    @GuardedBy("mRecordCallbackLock")
+    private void beginRecordingCallbackHandling() {
+        if (mRecordingCallbackHandlerThread == null) {
+            mRecordingCallbackHandlerThread = new HandlerThread(TAG + ".RecordingCallback");
+            mRecordingCallbackHandlerThread.start();
+            final Looper looper = mRecordingCallbackHandlerThread.getLooper();
+            if (looper != null) {
+                mRecordingCallbackHandler = new Handler(looper) {
+                    @Override
+                    public void handleMessage(Message msg) {
+                        switch (msg.what) {
+                            case MSG_RECORDING_CONFIG_CHANGE: {
+                                if (msg.obj == null) {
+                                    return;
+                                }
+                                ArrayList<AudioRecordingConfiguration> configs =
+                                        new ArrayList<AudioRecordingConfiguration>();
+                                configs.add((AudioRecordingConfiguration) msg.obj);
+
+                                final LinkedList<AudioRecordingCallbackInfo> cbInfoList;
+                                synchronized (mRecordCallbackLock) {
+                                    if (mRecordCallbackList.size() == 0) {
+                                        return;
+                                    }
+                                    cbInfoList = new LinkedList<AudioRecordingCallbackInfo>(
+                                        mRecordCallbackList);
+                                }
+
+                                final long identity = Binder.clearCallingIdentity();
+                                try {
+                                    for (AudioRecordingCallbackInfo cbi : cbInfoList) {
+                                        cbi.mExecutor.execute(() ->
+                                                cbi.mCb.onRecordingConfigChanged(configs));
+                                    }
+                                } finally {
+                                    Binder.restoreCallingIdentity(identity);
+                                }
+                            } break;
+                            default:
+                                Log.e(TAG, "Unknown event " + msg.what);
+                                break;
+                        }
+                    }
+                };
+                final IAudioService service = getService();
+                try {
+                    service.registerRecordingCallback(mRecordingCallback);
+                } catch (RemoteException e) {
+                    throw e.rethrowFromSystemServer();
+                }
+            }
+        }
+    }
+
+    @GuardedBy("mRecordCallbackLock")
+    private void endRecordingCallbackHandling() {
+        if (mRecordingCallbackHandlerThread != null) {
+            final IAudioService service = getService();
+            try {
+                service.unregisterRecordingCallback(mRecordingCallback);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+            mRecordingCallbackHandlerThread.quit();
+            mRecordingCallbackHandlerThread = null;
+        }
+    }
+
+    AudioRecordingConfiguration getMyConfig(List<AudioRecordingConfiguration> configs) {
+        int portId = mClient.getPortId();
+        for (AudioRecordingConfiguration config : configs) {
+            if (config.getClientPortId() == portId) {
+                return config;
+            }
+        }
+        return null;
+    }
+
+    private static IAudioService getService() {
+        if (sService != null) {
+            return sService;
+        }
+        IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
+        sService = IAudioService.Stub.asInterface(b);
+        return sService;
+    }
+}
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index a3702d6..34345b3 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -793,7 +793,7 @@
 
     // throws IllegalArgumentException if dsd is null or underline PFD of dsd has been closed.
     private void checkDataSourceDesc(DataSourceDesc dsd) {
-        if (dsd != null) {
+        if (dsd == null) {
             throw new IllegalArgumentException("dsd is expected to be non null");
         }
         if (dsd instanceof FileDataSourceDesc) {
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 8ced021..1cdc291 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -16,7 +16,9 @@
 
 package android.media;
 
+import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
@@ -40,6 +42,8 @@
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.Executor;
+
 
 /**
  * Used to record audio and video. The recording control is based on a
@@ -83,7 +87,9 @@
  * <a href="{@docRoot}guide/topics/media/audio-capture.html">Audio Capture</a> developer guide.</p>
  * </div>
  */
-public class MediaRecorder implements AudioRouting
+public class MediaRecorder implements AudioRouting,
+                                      AudioRecordingMonitor,
+                                      AudioRecordingMonitorClient
 {
     static {
         System.loadLibrary("media_jni");
@@ -304,7 +310,7 @@
 
         /**
          * Audio source for preemptible, low-priority software hotword detection
-         * It presents the same gain and pre processing tuning as {@link #VOICE_RECOGNITION}.
+         * It presents the same gain and pre-processing tuning as {@link #VOICE_RECOGNITION}.
          * <p>
          * An application should use this audio source when it wishes to do
          * always-on software hotword detection, while gracefully giving in to any other application
@@ -1471,6 +1477,57 @@
     private native final int native_getActiveMicrophones(
             ArrayList<MicrophoneInfo> activeMicrophones);
 
+    //--------------------------------------------------------------------------
+    // Implementation of AudioRecordingMonitor interface
+    //--------------------
+
+    AudioRecordingMonitorImpl mRecordingInfoImpl =
+            new AudioRecordingMonitorImpl((AudioRecordingMonitorClient) this);
+
+    /**
+     * Register a callback to be notified of audio capture changes via a
+     * {@link AudioManager.AudioRecordingCallback}. A callback is received when the capture path
+     * configuration changes (pre-processing, format, sampling rate...) or capture is
+     * silenced/unsilenced by the system.
+     * @param executor {@link Executor} to handle the callbacks.
+     * @param cb non-null callback to register
+     */
+    public void registerAudioRecordingCallback(@NonNull @CallbackExecutor Executor executor,
+            @NonNull AudioManager.AudioRecordingCallback cb) {
+        mRecordingInfoImpl.registerAudioRecordingCallback(executor, cb);
+    }
+
+    /**
+     * Unregister an audio recording callback previously registered with
+     * {@link #registerAudioRecordingCallback(Executor, AudioManager.AudioRecordingCallback)}.
+     * @param cb non-null callback to unregister
+     */
+    public void unregisterAudioRecordingCallback(@NonNull AudioManager.AudioRecordingCallback cb) {
+        mRecordingInfoImpl.unregisterAudioRecordingCallback(cb);
+    }
+
+    /**
+     * Returns the current active audio recording for this audio recorder.
+     * @return a valid {@link AudioRecordingConfiguration} if this recorder is active
+     * or null otherwise.
+     * @see AudioRecordingConfiguration
+     */
+    public @Nullable AudioRecordingConfiguration getActiveRecordingConfiguration() {
+        return mRecordingInfoImpl.getActiveRecordingConfiguration();
+    }
+
+    //---------------------------------------------------------
+    // Implementation of AudioRecordingMonitorClient interface
+    //--------------------
+    /**
+     * @hide
+     */
+    public int getPortId() {
+        return native_getPortId();
+    }
+
+    private native int native_getPortId();
+
     /**
      * Called from native code when an interesting event happens.  This method
      * just uses the EventHandler system to post the event back to the main app thread.
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index b3a8b21..ca30f32 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -763,6 +763,20 @@
     }
     return jStatus;
 }
+
+static jint android_media_MediaRecord_getPortId(JNIEnv *env,  jobject thiz) {
+    sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
+    if (mr == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return (jint)AUDIO_PORT_HANDLE_NONE;
+    }
+
+    audio_port_handle_t portId;
+    process_media_recorder_call(env, mr->getPortId(&portId),
+                                "java/lang/RuntimeException", "getPortId failed.");
+    return (jint)portId;
+}
+
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod gMethods[] = {
@@ -801,6 +815,7 @@
     {"native_enableDeviceCallback", "(Z)V",                     (void *)android_media_MediaRecorder_enableDeviceCallback},
 
     {"native_getActiveMicrophones", "(Ljava/util/ArrayList;)I", (void *)android_media_MediaRecord_getActiveMicrophones},
+    {"native_getPortId", "()I", (void *)android_media_MediaRecord_getPortId},
 };
 
 // This function only registers the native methods, and is called from
diff --git a/packages/CompanionDeviceManager/AndroidManifest.xml b/packages/CompanionDeviceManager/AndroidManifest.xml
index 0be71e6..42885e8 100644
--- a/packages/CompanionDeviceManager/AndroidManifest.xml
+++ b/packages/CompanionDeviceManager/AndroidManifest.xml
@@ -25,7 +25,7 @@
 
     <uses-permission android:name="android.permission.BLUETOOTH"/>
     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
-    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
     <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
diff --git a/packages/ExtServices/src/android/ext/services/notification/Assistant.java b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
index 54087d1..af52c00 100644
--- a/packages/ExtServices/src/android/ext/services/notification/Assistant.java
+++ b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
@@ -117,7 +117,7 @@
         mPackageManager = ActivityThread.getPackageManager();
         mSettings = mSettingsFactory.createAndRegister(mHandler,
                 getApplicationContext().getContentResolver(), getUserId(), this::updateThresholds);
-        mSmartActionsHelper = new SmartActionsHelper();
+        mSmartActionsHelper = new SmartActionsHelper(getContext(), mSettings);
         mNotificationCategorizer = new NotificationCategorizer();
         mAgingHelper = new AgingHelper(getContext(),
                 mNotificationCategorizer,
@@ -215,10 +215,8 @@
             return null;
         }
         NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel);
-        ArrayList<Notification.Action> actions =
-                mSmartActionsHelper.suggestActions(this, entry, mSettings);
-        ArrayList<CharSequence> replies =
-                mSmartActionsHelper.suggestReplies(this, entry, mSettings);
+        ArrayList<Notification.Action> actions = mSmartActionsHelper.suggestActions(entry);
+        ArrayList<CharSequence> replies = mSmartActionsHelper.suggestReplies(entry);
         return createEnqueuedNotificationAdjustment(entry, actions, replies);
     }
 
@@ -343,6 +341,7 @@
                 if (entry != null) {
                     entry.setSeen();
                     mAgingHelper.onNotificationSeen(entry);
+                    mSmartActionsHelper.onNotificationSeen(entry);
                 }
             }
         } catch (Throwable e) {
@@ -351,34 +350,46 @@
     }
 
     @Override
-    public void onNotificationExpansionChanged(String key, boolean isUserAction,
+    public void onNotificationExpansionChanged(@NonNull String key, boolean isUserAction,
             boolean isExpanded) {
         if (DEBUG) {
-            Log.i(TAG,
-                    "onNotificationExpansionChanged " + key + ", isUserAction =" + isUserAction
-                            + ", isExpanded = isExpanded");
+            Log.d(TAG, "onNotificationExpansionChanged() called with: key = [" + key
+                    + "], isUserAction = [" + isUserAction + "], isExpanded = [" + isExpanded
+                    + "]");
+        }
+        NotificationEntry entry = mLiveNotifications.get(key);
+
+        if (entry != null) {
+            entry.setExpanded(isExpanded);
+            mSmartActionsHelper.onNotificationExpansionChanged(entry, isUserAction, isExpanded);
         }
     }
 
     @Override
-    public void onNotificationDirectReply(String key) {
+    public void onNotificationDirectReply(@NonNull String key) {
         if (DEBUG) Log.i(TAG, "onNotificationDirectReply " + key);
+        mSmartActionsHelper.onNotificationDirectReply(key);
     }
 
     @Override
-    public void onSuggestedReplySent(String key, CharSequence reply, int source) {
+    public void onSuggestedReplySent(@NonNull String key, @NonNull CharSequence reply,
+            @Source int source) {
         if (DEBUG) {
             Log.d(TAG, "onSuggestedReplySent() called with: key = [" + key + "], reply = [" + reply
                     + "], source = [" + source + "]");
         }
+        mSmartActionsHelper.onSuggestedReplySent(key, reply, source);
     }
 
     @Override
-    public void onActionClicked(String key, Notification.Action action, int source) {
+    public void onActionClicked(@NonNull String key, @NonNull Notification.Action action,
+            @Source int source) {
         if (DEBUG) {
-            Log.d(TAG, "onActionClicked() called with: key = [" + key + "], action = [" + action.title
-                    + "], source = [" + source + "]");
+            Log.d(TAG,
+                    "onActionClicked() called with: key = [" + key + "], action = [" + action.title
+                            + "], source = [" + source + "]");
         }
+        mSmartActionsHelper.onActionClicked(key, action, source);
     }
 
     @Override
diff --git a/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java b/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java
index 6f437bd5..71fd9ce 100644
--- a/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java
+++ b/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java
@@ -52,6 +52,8 @@
     private NotificationChannel mChannel;
     private int mImportance;
     private boolean mSeen;
+    private boolean mExpanded;
+    private boolean mIsShowActionEventLogged;
 
     public NotificationEntry(IPackageManager packageManager, StatusBarNotification sbn,
             NotificationChannel channel) {
@@ -216,10 +218,26 @@
         mSeen = true;
     }
 
+    public void setExpanded(boolean expanded) {
+        mExpanded = expanded;
+    }
+
+    public void setShowActionEventLogged() {
+        mIsShowActionEventLogged = true;
+    }
+
     public boolean hasSeen() {
         return mSeen;
     }
 
+    public boolean isExpanded() {
+        return mExpanded;
+    }
+
+    public boolean isShowActionEventLogged() {
+        return mIsShowActionEventLogged;
+    }
+
     public StatusBarNotification getSbn() {
         return mSbn;
     }
diff --git a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
index 38df9b0..b041842 100644
--- a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
+++ b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
@@ -24,12 +24,16 @@
 import android.os.Bundle;
 import android.os.Parcelable;
 import android.os.Process;
+import android.service.notification.NotificationAssistantService;
 import android.text.TextUtils;
 import android.util.ArrayMap;
+import android.util.LruCache;
 import android.view.textclassifier.ConversationActions;
 import android.view.textclassifier.TextClassification;
+import android.view.textclassifier.TextClassificationContext;
 import android.view.textclassifier.TextClassificationManager;
 import android.view.textclassifier.TextClassifier;
+import android.view.textclassifier.TextClassifierEvent;
 import android.view.textclassifier.TextLinks;
 
 import java.time.Instant;
@@ -47,6 +51,7 @@
     private static final ArrayList<Notification.Action> EMPTY_ACTION_LIST = new ArrayList<>();
     private static final ArrayList<CharSequence> EMPTY_REPLY_LIST = new ArrayList<>();
 
+    private static final String KEY_ACTION_TYPE = "action_type";
     // If a notification has any of these flags set, it's inelgibile for actions being added.
     private static final int FLAG_MASK_INELGIBILE_FOR_ACTIONS =
             Notification.FLAG_ONGOING_EVENT
@@ -59,6 +64,7 @@
     private static final int MAX_SUGGESTED_REPLIES = 3;
     // TODO: Make this configurable.
     private static final int MAX_MESSAGES_TO_EXTRACT = 5;
+    private static final int MAX_RESULT_ID_TO_CACHE = 20;
 
     private static final ConversationActions.TypeConfig TYPE_CONFIG =
             new ConversationActions.TypeConfig.Builder().setIncludedTypes(
@@ -68,26 +74,36 @@
     private static final List<String> HINTS =
             Collections.singletonList(ConversationActions.HINT_FOR_NOTIFICATION);
 
-    SmartActionsHelper() {
+    private Context mContext;
+    @Nullable
+    private TextClassifier mTextClassifier;
+    @NonNull
+    private AssistantSettings mSettings;
+    private LruCache<String, String> mNotificationKeyToResultIdCache =
+            new LruCache<>(MAX_RESULT_ID_TO_CACHE);
+
+    SmartActionsHelper(Context context, AssistantSettings settings) {
+        mContext = context;
+        TextClassificationManager textClassificationManager =
+                mContext.getSystemService(TextClassificationManager.class);
+        if (textClassificationManager != null) {
+            mTextClassifier = textClassificationManager.getTextClassifier();
+        }
+        mSettings = settings;
     }
 
     /**
      * Adds action adjustments based on the notification contents.
      */
     @NonNull
-    ArrayList<Notification.Action> suggestActions(@Nullable Context context,
-            @NonNull NotificationEntry entry, @NonNull AssistantSettings settings) {
-        if (!settings.mGenerateActions) {
+    ArrayList<Notification.Action> suggestActions(@NonNull NotificationEntry entry) {
+        if (!mSettings.mGenerateActions) {
             return EMPTY_ACTION_LIST;
         }
         if (!isEligibleForActionAdjustment(entry)) {
             return EMPTY_ACTION_LIST;
         }
-        if (context == null) {
-            return EMPTY_ACTION_LIST;
-        }
-        TextClassificationManager tcm = context.getSystemService(TextClassificationManager.class);
-        if (tcm == null) {
+        if (mTextClassifier == null) {
             return EMPTY_ACTION_LIST;
         }
         List<ConversationActions.Message> messages = extractMessages(entry.getNotification());
@@ -96,22 +112,17 @@
         }
         // TODO: Move to TextClassifier.suggestConversationActions once it is ready.
         return suggestActionsFromText(
-                tcm, messages.get(messages.size() - 1).getText(), MAX_SMART_ACTIONS);
+                messages.get(messages.size() - 1).getText(), MAX_SMART_ACTIONS);
     }
 
-    ArrayList<CharSequence> suggestReplies(@Nullable Context context,
-            @NonNull NotificationEntry entry, @NonNull AssistantSettings settings) {
-        if (!settings.mGenerateReplies) {
+    ArrayList<CharSequence> suggestReplies(@NonNull NotificationEntry entry) {
+        if (!mSettings.mGenerateReplies) {
             return EMPTY_REPLY_LIST;
         }
         if (!isEligibleForReplyAdjustment(entry)) {
             return EMPTY_REPLY_LIST;
         }
-        if (context == null) {
-            return EMPTY_REPLY_LIST;
-        }
-        TextClassificationManager tcm = context.getSystemService(TextClassificationManager.class);
-        if (tcm == null) {
+        if (mTextClassifier == null) {
             return EMPTY_REPLY_LIST;
         }
         List<ConversationActions.Message> messages = extractMessages(entry.getNotification());
@@ -125,14 +136,122 @@
                         .setTypeConfig(TYPE_CONFIG)
                         .build();
 
-        TextClassifier textClassifier = tcm.getTextClassifier();
+        ConversationActions conversationActionsResult =
+                mTextClassifier.suggestConversationActions(request);
         List<ConversationActions.ConversationAction> conversationActions =
-                textClassifier.suggestConversationActions(request).getConversationActions();
-
-        return conversationActions.stream()
+                conversationActionsResult.getConversationActions();
+        ArrayList<CharSequence> replies = conversationActions.stream()
                 .map(conversationAction -> conversationAction.getTextReply())
                 .filter(textReply -> !TextUtils.isEmpty(textReply))
                 .collect(Collectors.toCollection(ArrayList::new));
+
+        String resultId = conversationActionsResult.getId();
+        if (resultId != null && !replies.isEmpty()) {
+            mNotificationKeyToResultIdCache.put(entry.getSbn().getKey(), resultId);
+        }
+        return replies;
+    }
+
+    void onNotificationSeen(@NonNull NotificationEntry entry) {
+        if (entry.isExpanded()) {
+            maybeSendActionShownEvent(entry);
+        }
+    }
+
+    void onNotificationExpansionChanged(@NonNull NotificationEntry entry, boolean isUserAction,
+            boolean isExpanded) {
+        // Notification can be expanded in the background, and thus the isUserAction check.
+        if (isUserAction && isExpanded) {
+            maybeSendActionShownEvent(entry);
+        }
+    }
+
+    void onNotificationDirectReply(@NonNull String key) {
+        if (mTextClassifier == null) {
+            return;
+        }
+        String resultId = mNotificationKeyToResultIdCache.get(key);
+        if (resultId == null) {
+            return;
+        }
+        TextClassifierEvent textClassifierEvent =
+                createTextClassifierEventBuilder(TextClassifierEvent.TYPE_MANUAL_REPLY, resultId)
+                        .build();
+        mTextClassifier.onTextClassifierEvent(textClassifierEvent);
+    }
+
+    void onSuggestedReplySent(@NonNull String key, @NonNull CharSequence reply,
+            @NotificationAssistantService.Source int source) {
+        if (mTextClassifier == null) {
+            return;
+        }
+        if (source != NotificationAssistantService.SOURCE_FROM_ASSISTANT) {
+            return;
+        }
+        String resultId = mNotificationKeyToResultIdCache.get(key);
+        if (resultId == null) {
+            return;
+        }
+        TextClassifierEvent textClassifierEvent =
+                createTextClassifierEventBuilder(TextClassifierEvent.TYPE_SMART_ACTION, resultId)
+                        .setEntityType(ConversationActions.TYPE_TEXT_REPLY)
+                        .build();
+        mTextClassifier.onTextClassifierEvent(textClassifierEvent);
+    }
+
+    void onActionClicked(@NonNull String key, @NonNull Notification.Action action,
+            @NotificationAssistantService.Source int source) {
+        if (mTextClassifier == null) {
+            return;
+        }
+        if (source != NotificationAssistantService.SOURCE_FROM_ASSISTANT) {
+            return;
+        }
+        String resultId = mNotificationKeyToResultIdCache.get(key);
+        if (resultId == null) {
+            return;
+        }
+        String actionType = action.getExtras().getString(KEY_ACTION_TYPE);
+        if (actionType == null) {
+            return;
+        }
+        TextClassifierEvent textClassifierEvent =
+                createTextClassifierEventBuilder(TextClassifierEvent.TYPE_SMART_ACTION, resultId)
+                        .setEntityType(actionType)
+                        .build();
+        mTextClassifier.onTextClassifierEvent(textClassifierEvent);
+    }
+
+    private TextClassifierEvent.Builder createTextClassifierEventBuilder(
+            int eventType, @NonNull String resultId) {
+        return new TextClassifierEvent.Builder(
+                TextClassifierEvent.CATEGORY_CONVERSATION_ACTIONS, eventType)
+                .setEventTime(System.currentTimeMillis())
+                .setEventContext(
+                        new TextClassificationContext.Builder(
+                                mContext.getPackageName(), TextClassifier.WIDGET_TYPE_NOTIFICATION)
+                        .build())
+                .setResultId(resultId);
+    }
+
+    private void maybeSendActionShownEvent(@NonNull NotificationEntry entry) {
+        if (mTextClassifier == null) {
+            return;
+        }
+        String resultId = mNotificationKeyToResultIdCache.get(entry.getSbn().getKey());
+        if (resultId == null) {
+            return;
+        }
+        // Only report if this is the first time the user sees these suggestions.
+        if (entry.isShowActionEventLogged()) {
+            return;
+        }
+        entry.setShowActionEventLogged();
+        TextClassifierEvent textClassifierEvent =
+                createTextClassifierEventBuilder(TextClassifierEvent.TYPE_ACTIONS_SHOWN, resultId)
+                        .build();
+        // TODO: If possible, report which replies / actions are actually seen by user.
+        mTextClassifier.onTextClassifierEvent(textClassifierEvent);
     }
 
     /**
@@ -220,13 +339,10 @@
     /** Returns a list of actions to act on entities in a given piece of text. */
     @NonNull
     private ArrayList<Notification.Action> suggestActionsFromText(
-            @NonNull TextClassificationManager tcm, @Nullable CharSequence text,
-            int maxSmartActions) {
+            @Nullable CharSequence text, int maxSmartActions) {
         if (TextUtils.isEmpty(text)) {
             return EMPTY_ACTION_LIST;
         }
-        TextClassifier textClassifier = tcm.getTextClassifier();
-
         // We want to process only text visible to the user to avoid confusing suggestions, so we
         // truncate the text to a reasonable length. This is particularly important for e.g.
         // email apps that sometimes include the text for the entire thread.
@@ -239,7 +355,7 @@
                                 Collections.singletonList(
                                         TextClassifier.HINT_TEXT_IS_NOT_EDITABLE)))
                 .build();
-        TextLinks links = textClassifier.generateLinks(textLinksRequest);
+        TextLinks links = mTextClassifier.generateLinks(textLinksRequest);
         ArrayMap<String, Integer> entityTypeFrequency = getEntityTypeFrequency(links);
 
         ArrayList<Notification.Action> actions = new ArrayList<>();
@@ -254,19 +370,26 @@
 
             // Generate the actions, and add the most prominent ones to the action bar.
             TextClassification classification =
-                    textClassifier.classifyText(
+                    mTextClassifier.classifyText(
                             new TextClassification.Request.Builder(
                                     text, link.getStart(), link.getEnd()).build());
+            if (classification.getEntityCount() == 0) {
+                continue;
+            }
             int numOfActions = Math.min(
                     MAX_ACTIONS_PER_LINK, classification.getActions().size());
             for (int i = 0; i < numOfActions; ++i) {
-                RemoteAction action = classification.getActions().get(i);
-                actions.add(
-                        new Notification.Action.Builder(
-                                action.getIcon(),
-                                action.getTitle(),
-                                action.getActionIntent())
-                                .build());
+                RemoteAction remoteAction = classification.getActions().get(i);
+                Notification.Action action = new Notification.Action.Builder(
+                        remoteAction.getIcon(),
+                        remoteAction.getTitle(),
+                        remoteAction.getActionIntent())
+                        .setSemanticAction(
+                                Notification.Action.SEMANTIC_ACTION_CONTEXTUAL_SUGGESTION)
+                        .addExtras(Bundle.forPair(KEY_ACTION_TYPE, classification.getEntity(0)))
+                        .build();
+                actions.add(action);
+
                 // We have enough smart actions.
                 if (actions.size() >= maxSmartActions) {
                     return actions;
diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionHelperTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionHelperTest.java
index 0352ebc..da382a0 100644
--- a/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionHelperTest.java
+++ b/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionHelperTest.java
@@ -28,12 +28,14 @@
 import android.app.Person;
 import android.content.Context;
 import android.os.Process;
+import android.service.notification.NotificationAssistantService;
 import android.service.notification.StatusBarNotification;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
 import android.view.textclassifier.ConversationActions;
 import android.view.textclassifier.TextClassificationManager;
 import android.view.textclassifier.TextClassifier;
+import android.view.textclassifier.TextClassifierEvent;
 
 import com.google.common.truth.FailureStrategy;
 import com.google.common.truth.Subject;
@@ -44,12 +46,14 @@
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
 import java.time.Instant;
 import java.time.ZoneOffset;
 import java.time.ZonedDateTime;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
@@ -58,8 +62,14 @@
 
 @RunWith(AndroidJUnit4.class)
 public class SmartActionHelperTest {
+    private static final String NOTIFICATION_KEY = "key";
+    private static final String RESULT_ID = "id";
 
-    private SmartActionsHelper mSmartActionsHelper = new SmartActionsHelper();
+    private static final ConversationActions.ConversationAction REPLY_ACTION =
+            new ConversationActions.ConversationAction.Builder(
+                    ConversationActions.TYPE_TEXT_REPLY).setTextReply("Home").build();
+
+    private SmartActionsHelper mSmartActionsHelper;
     private Context mContext;
     @Mock private TextClassifier mTextClassifier;
     @Mock private NotificationEntry mNotificationEntry;
@@ -75,7 +85,7 @@
         mContext.getSystemService(TextClassificationManager.class)
                 .setTextClassifier(mTextClassifier);
         when(mTextClassifier.suggestConversationActions(any(ConversationActions.Request.class)))
-                .thenReturn(new ConversationActions(Collections.emptyList(), null));
+                .thenReturn(new ConversationActions(Arrays.asList(REPLY_ACTION), RESULT_ID));
 
         when(mNotificationEntry.getSbn()).thenReturn(mStatusBarNotification);
         // The notification is eligible to have smart suggestions.
@@ -83,18 +93,20 @@
         when(mNotificationEntry.isMessaging()).thenReturn(true);
         when(mStatusBarNotification.getPackageName()).thenReturn("random.app");
         when(mStatusBarNotification.getUser()).thenReturn(Process.myUserHandle());
+        when(mStatusBarNotification.getKey()).thenReturn(NOTIFICATION_KEY);
         mNotificationBuilder = new Notification.Builder(mContext, "channel");
         mSettings = AssistantSettings.createForTesting(
                 null, null, Process.myUserHandle().getIdentifier(), null);
         mSettings.mGenerateActions = true;
         mSettings.mGenerateReplies = true;
+        mSmartActionsHelper = new SmartActionsHelper(mContext, mSettings);
     }
 
     @Test
     public void testSuggestReplies_notMessagingApp() {
         when(mNotificationEntry.isMessaging()).thenReturn(false);
         ArrayList<CharSequence> textReplies =
-                mSmartActionsHelper.suggestReplies(mContext, mNotificationEntry, mSettings);
+                mSmartActionsHelper.suggestReplies(mNotificationEntry);
         assertThat(textReplies).isEmpty();
     }
 
@@ -102,7 +114,7 @@
     public void testSuggestReplies_noInlineReply() {
         when(mNotificationEntry.hasInlineReply()).thenReturn(false);
         ArrayList<CharSequence> textReplies =
-                mSmartActionsHelper.suggestReplies(mContext, mNotificationEntry, mSettings);
+                mSmartActionsHelper.suggestReplies(mNotificationEntry);
         assertThat(textReplies).isEmpty();
     }
 
@@ -169,18 +181,128 @@
                         .build();
         when(mNotificationEntry.getNotification()).thenReturn(notification);
 
-        mSmartActionsHelper.suggestReplies(mContext, mNotificationEntry, mSettings);
+        mSmartActionsHelper.suggestReplies(mNotificationEntry);
 
         verify(mTextClassifier, never())
                 .suggestConversationActions(any(ConversationActions.Request.class));
     }
 
+    @Test
+    public void testOnSuggestedReplySent() {
+        final String message = "Where are you?";
+        Notification notification = mNotificationBuilder.setContentText(message).build();
+        when(mNotificationEntry.getNotification()).thenReturn(notification);
+
+        mSmartActionsHelper.suggestReplies(mNotificationEntry);
+        mSmartActionsHelper.onSuggestedReplySent(
+                NOTIFICATION_KEY, message, NotificationAssistantService.SOURCE_FROM_ASSISTANT);
+
+        ArgumentCaptor<TextClassifierEvent> argumentCaptor =
+                ArgumentCaptor.forClass(TextClassifierEvent.class);
+        verify(mTextClassifier).onTextClassifierEvent(argumentCaptor.capture());
+        TextClassifierEvent textClassifierEvent = argumentCaptor.getValue();
+        assertTextClassifierEvent(textClassifierEvent, TextClassifierEvent.TYPE_SMART_ACTION);
+    }
+
+    @Test
+    public void testOnSuggestedReplySent_anotherNotification() {
+        final String message = "Where are you?";
+        Notification notification = mNotificationBuilder.setContentText(message).build();
+        when(mNotificationEntry.getNotification()).thenReturn(notification);
+
+        mSmartActionsHelper.suggestReplies(mNotificationEntry);
+        mSmartActionsHelper.onSuggestedReplySent(
+                "something_else", message, NotificationAssistantService.SOURCE_FROM_ASSISTANT);
+
+        verify(mTextClassifier, never())
+                .onTextClassifierEvent(Mockito.any(TextClassifierEvent.class));
+    }
+
+    @Test
+    public void testOnSuggestedReplySent_missingResultId() {
+        when(mTextClassifier.suggestConversationActions(any(ConversationActions.Request.class)))
+                .thenReturn(new ConversationActions(Collections.emptyList(), null));
+
+        final String message = "Where are you?";
+        Notification notification = mNotificationBuilder.setContentText(message).build();
+        when(mNotificationEntry.getNotification()).thenReturn(notification);
+
+        mSmartActionsHelper.suggestReplies(mNotificationEntry);
+        mSmartActionsHelper.onSuggestedReplySent(
+                "something_else", message, NotificationAssistantService.SOURCE_FROM_ASSISTANT);
+
+        verify(mTextClassifier, never())
+                .onTextClassifierEvent(Mockito.any(TextClassifierEvent.class));
+    }
+
+    @Test
+    public void testOnNotificationDirectReply() {
+        Notification notification = mNotificationBuilder.setContentText("Where are you?").build();
+        when(mNotificationEntry.getNotification()).thenReturn(notification);
+
+        mSmartActionsHelper.suggestReplies(mNotificationEntry);
+        mSmartActionsHelper.onNotificationDirectReply(NOTIFICATION_KEY);
+
+        ArgumentCaptor<TextClassifierEvent> argumentCaptor =
+                ArgumentCaptor.forClass(TextClassifierEvent.class);
+        verify(mTextClassifier).onTextClassifierEvent(argumentCaptor.capture());
+        TextClassifierEvent textClassifierEvent = argumentCaptor.getValue();
+        assertTextClassifierEvent(textClassifierEvent, TextClassifierEvent.TYPE_MANUAL_REPLY);
+    }
+
+    @Test
+    public void testOnNotificationExpansionChanged() {
+        final String message = "Where are you?";
+        Notification notification = mNotificationBuilder.setContentText(message).build();
+        when(mNotificationEntry.getNotification()).thenReturn(notification);
+
+        mSmartActionsHelper.suggestReplies(mNotificationEntry);
+        mSmartActionsHelper.onNotificationExpansionChanged(mNotificationEntry, true, true);
+
+        ArgumentCaptor<TextClassifierEvent> argumentCaptor =
+                ArgumentCaptor.forClass(TextClassifierEvent.class);
+        verify(mTextClassifier).onTextClassifierEvent(argumentCaptor.capture());
+        TextClassifierEvent textClassifierEvent = argumentCaptor.getValue();
+        assertTextClassifierEvent(textClassifierEvent, TextClassifierEvent.TYPE_ACTIONS_SHOWN);
+    }
+
+    @Test
+    public void testOnNotificationsSeen_notExpanded() {
+        final String message = "Where are you?";
+        Notification notification = mNotificationBuilder.setContentText(message).build();
+        when(mNotificationEntry.getNotification()).thenReturn(notification);
+        when(mNotificationEntry.isExpanded()).thenReturn(false);
+
+        mSmartActionsHelper.suggestReplies(mNotificationEntry);
+        mSmartActionsHelper.onNotificationSeen(mNotificationEntry);
+
+        verify(mTextClassifier, never()).onTextClassifierEvent(
+                Mockito.any(TextClassifierEvent.class));
+    }
+
+    @Test
+    public void testOnNotificationsSeen_expanded() {
+        final String message = "Where are you?";
+        Notification notification = mNotificationBuilder.setContentText(message).build();
+        when(mNotificationEntry.getNotification()).thenReturn(notification);
+        when(mNotificationEntry.isExpanded()).thenReturn(true);
+
+        mSmartActionsHelper.suggestReplies(mNotificationEntry);
+        mSmartActionsHelper.onNotificationSeen(mNotificationEntry);
+
+        ArgumentCaptor<TextClassifierEvent> argumentCaptor =
+                ArgumentCaptor.forClass(TextClassifierEvent.class);
+        verify(mTextClassifier).onTextClassifierEvent(argumentCaptor.capture());
+        TextClassifierEvent textClassifierEvent = argumentCaptor.getValue();
+        assertTextClassifierEvent(textClassifierEvent, TextClassifierEvent.TYPE_ACTIONS_SHOWN);
+    }
+
     private ZonedDateTime createZonedDateTimeFromMsUtc(long msUtc) {
         return ZonedDateTime.ofInstant(Instant.ofEpochMilli(msUtc), ZoneOffset.systemDefault());
     }
 
     private List<ConversationActions.Message> getMessagesInRequest() {
-        mSmartActionsHelper.suggestReplies(mContext, mNotificationEntry, mSettings);
+        mSmartActionsHelper.suggestReplies(mNotificationEntry);
 
         ArgumentCaptor<ConversationActions.Request> argumentCaptor =
                 ArgumentCaptor.forClass(ConversationActions.Request.class);
@@ -189,6 +311,17 @@
         return request.getConversation();
     }
 
+    private void assertTextClassifierEvent(
+            TextClassifierEvent textClassifierEvent, int expectedEventType) {
+        assertThat(textClassifierEvent.getEventCategory())
+                .isEqualTo(TextClassifierEvent.CATEGORY_CONVERSATION_ACTIONS);
+        assertThat(textClassifierEvent.getEventContext().getPackageName())
+                .isEqualTo(InstrumentationRegistry.getTargetContext().getPackageName());
+        assertThat(textClassifierEvent.getEventContext().getWidgetType())
+                .isEqualTo(TextClassifier.WIDGET_TYPE_NOTIFICATION);
+        assertThat(textClassifierEvent.getEventType()).isEqualTo(expectedEventType);
+    }
+
     private static final class MessageSubject
             extends Subject<MessageSubject, ConversationActions.Message> {
 
diff --git a/packages/ExternalStorageProvider/tests/Android.bp b/packages/ExternalStorageProvider/tests/Android.bp
index 83427d4..04cf01a 100644
--- a/packages/ExternalStorageProvider/tests/Android.bp
+++ b/packages/ExternalStorageProvider/tests/Android.bp
@@ -14,7 +14,7 @@
     ],
 
     static_libs: [
-        "android-support-test",
+        "androidx.test.rules",
         "mockito-target",
         "truth-prebuilt",
     ],
diff --git a/packages/ExternalStorageProvider/tests/AndroidManifest.xml b/packages/ExternalStorageProvider/tests/AndroidManifest.xml
index 58b6e86..f1a6af0 100644
--- a/packages/ExternalStorageProvider/tests/AndroidManifest.xml
+++ b/packages/ExternalStorageProvider/tests/AndroidManifest.xml
@@ -6,7 +6,7 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.externalstorage"
                      android:label="ExternalStorageProvider Tests" />
 </manifest>
diff --git a/packages/ExternalStorageProvider/tests/AndroidTest.xml b/packages/ExternalStorageProvider/tests/AndroidTest.xml
index e5fa73f..f8438b2 100644
--- a/packages/ExternalStorageProvider/tests/AndroidTest.xml
+++ b/packages/ExternalStorageProvider/tests/AndroidTest.xml
@@ -23,7 +23,7 @@
     <option name="test-tag" value="ExternalStorageProviderTests" />
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.externalstorage.tests" />
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
         <option name="hidden-api-checks" value="false"/>
     </test>
 </configuration>
diff --git a/packages/ExternalStorageProvider/tests/src/com/android/externalstorage/ExternalStorageProviderTest.java b/packages/ExternalStorageProvider/tests/src/com/android/externalstorage/ExternalStorageProviderTest.java
index a88b3e1..fbf2e4b 100644
--- a/packages/ExternalStorageProvider/tests/src/com/android/externalstorage/ExternalStorageProviderTest.java
+++ b/packages/ExternalStorageProvider/tests/src/com/android/externalstorage/ExternalStorageProviderTest.java
@@ -23,8 +23,9 @@
 import static org.mockito.Mockito.verify;
 
 import android.content.pm.ProviderInfo;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/packages/SettingsLib/tests/integ/Android.mk b/packages/SettingsLib/tests/integ/Android.mk
index c893b6d..4a814df 100644
--- a/packages/SettingsLib/tests/integ/Android.mk
+++ b/packages/SettingsLib/tests/integ/Android.mk
@@ -31,8 +31,8 @@
 LOCAL_USE_AAPT2 := true
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
-    android-support-test \
-    espresso-core \
+    androidx.test.rules \
+    androidx.test.espresso.core \
     mockito-target-minus-junit4 \
     truth-prebuilt
 
diff --git a/packages/SettingsLib/tests/integ/AndroidManifest.xml b/packages/SettingsLib/tests/integ/AndroidManifest.xml
index e8e0b41..da808dd 100644
--- a/packages/SettingsLib/tests/integ/AndroidManifest.xml
+++ b/packages/SettingsLib/tests/integ/AndroidManifest.xml
@@ -31,7 +31,7 @@
         <activity android:name=".drawer.SettingsDrawerActivityTest$TestActivity"/>
     </application>
 
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
         android:targetPackage="com.android.settingslib"
         android:label="Tests for SettingsLib">
     </instrumentation>
diff --git a/packages/SettingsLib/tests/integ/AndroidTest.xml b/packages/SettingsLib/tests/integ/AndroidTest.xml
index d7ee618..b5d0947 100644
--- a/packages/SettingsLib/tests/integ/AndroidTest.xml
+++ b/packages/SettingsLib/tests/integ/AndroidTest.xml
@@ -22,7 +22,7 @@
     <option name="test-tag" value="SettingsLibTests" />
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.settingslib" />
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
         <option name="hidden-api-checks" value="false"/>
     </test>
 </configuration>
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/bluetooth/BluetoothEventManagerIntegTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/bluetooth/BluetoothEventManagerIntegTest.java
index d0ab46a..50f5b9d 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/bluetooth/BluetoothEventManagerIntegTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/bluetooth/BluetoothEventManagerIntegTest.java
@@ -16,15 +16,10 @@
 
 package com.android.settingslib.bluetooth;
 
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.Mockito.mock;
 
-import static java.util.concurrent.TimeUnit.SECONDS;
-
 import android.app.ActivityManager;
 import android.content.Context;
 import android.content.Intent;
@@ -32,15 +27,18 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import static java.util.concurrent.TimeUnit.SECONDS;
+
 import java.util.concurrent.CountDownLatch;
 
 /**
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawable/UserIconDrawableTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawable/UserIconDrawableTest.java
index 3fa2ce5..a436cb5 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawable/UserIconDrawableTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawable/UserIconDrawableTest.java
@@ -27,8 +27,9 @@
 import android.graphics.Color;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuff.Mode;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.settingslib.R;
 
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
index dddfa7a..08484bc 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
@@ -1,19 +1,7 @@
 package com.android.settingslib.graph;
 
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import com.android.settingslib.R;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
 import static com.google.common.truth.Truth.assertThat;
-import static junit.framework.Assert.assertTrue;
+
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyFloat;
 import static org.mockito.Matchers.anyString;
@@ -21,6 +9,21 @@
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.settingslib.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class BatteryMeterDrawableBaseTest {
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodPreferenceTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodPreferenceTest.java
index 93b038e..9962e1c 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodPreferenceTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodPreferenceTest.java
@@ -20,12 +20,13 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodSubtype;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodSubtypePreferenceTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodSubtypePreferenceTest.java
index e591d8c..f1c0bea 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodSubtypePreferenceTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodSubtypePreferenceTest.java
@@ -16,11 +16,12 @@
 
 package com.android.settingslib.inputmethod;
 
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.TextUtils;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/UserManagerHelperTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/UserManagerHelperTest.java
index 54510b2..46557d3 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/UserManagerHelperTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/UserManagerHelperTest.java
@@ -18,7 +18,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -33,8 +32,9 @@
 import android.os.Handler;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/NetworkPolicyEditorTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/NetworkPolicyEditorTest.java
index ee03d50..37f2600 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/NetworkPolicyEditorTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/NetworkPolicyEditorTest.java
@@ -16,19 +16,22 @@
 
 package com.android.settingslib.utils;
 
+import static junit.framework.Assert.assertEquals;
+
 import android.net.NetworkPolicy;
 import android.net.NetworkPolicyManager;
 import android.net.NetworkTemplate;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.settingslib.NetworkPolicyEditor;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import static junit.framework.Assert.assertEquals;
-
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class NetworkPolicyEditorTest {
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/ZoneGetterTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/ZoneGetterTest.java
index 0ec75ec..ff8dbda 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/ZoneGetterTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/ZoneGetterTest.java
@@ -15,21 +15,23 @@
  */
 package com.android.settingslib.utils;
 
+import static junit.framework.Assert.assertTrue;
+
 import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
-import android.support.test.filters.SmallTest;
 import android.text.Spanned;
 import android.text.style.TtsSpan;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.settingslib.datetime.ZoneGetter;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import java.util.*;
-import com.android.settingslib.datetime.ZoneGetter;
-
-import static junit.framework.Assert.assertTrue;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index 03247999..fc3034e 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -22,7 +22,6 @@
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -44,12 +43,12 @@
 import android.os.Bundle;
 import android.os.Parcelable;
 import android.os.SystemClock;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.SpannableString;
 import android.text.format.DateUtils;
-import android.text.style.TtsSpan;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.settingslib.R;
 import com.android.settingslib.utils.ThreadUtils;
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index 1860b31..42eb0b9 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -53,9 +53,10 @@
 import android.os.HandlerThread;
 import android.os.SystemClock;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.settingslib.utils.ThreadUtils;
 
@@ -79,7 +80,6 @@
 import java.util.concurrent.atomic.AtomicBoolean;
 
 // TODO(sghuman): Change these to robolectric tests b/35766684.
-
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class WifiTrackerTest {
diff --git a/packages/SimAppDialog/src/com/android/simappdialog/InstallCarrierAppActivity.java b/packages/SimAppDialog/src/com/android/simappdialog/InstallCarrierAppActivity.java
index 8e8d9f7..abe82a8 100644
--- a/packages/SimAppDialog/src/com/android/simappdialog/InstallCarrierAppActivity.java
+++ b/packages/SimAppDialog/src/com/android/simappdialog/InstallCarrierAppActivity.java
@@ -18,7 +18,7 @@
 import android.app.Activity;
 import android.content.Intent;
 import android.os.Bundle;
-import android.os.SystemProperties;
+import android.sysprop.SetupWizardProperties;
 import android.text.TextUtils;
 import android.view.View;
 import android.widget.Button;
@@ -51,7 +51,7 @@
         // Setup theme for aosp/pixel
         setTheme(
                 WizardManagerHelper.getThemeRes(
-                        SystemProperties.get("setupwizard.theme"),
+                        SetupWizardProperties.theme().orElse(""),
                         R.style.SuwThemeGlif_Light
                 )
         );
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index 201c7e6..9a8a6d0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -41,6 +41,8 @@
 import androidx.slice.builders.SliceAction;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.policy.NextAlarmController;
 import com.android.systemui.statusbar.policy.NextAlarmControllerImpl;
@@ -49,6 +51,7 @@
 
 import java.util.Date;
 import java.util.Locale;
+import java.util.TimeZone;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -100,21 +103,28 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             final String action = intent.getAction();
-            if (Intent.ACTION_TIME_TICK.equals(action)
-                    || Intent.ACTION_DATE_CHANGED.equals(action)
-                    || Intent.ACTION_TIME_CHANGED.equals(action)
-                    || Intent.ACTION_TIMEZONE_CHANGED.equals(action)
-                    || Intent.ACTION_LOCALE_CHANGED.equals(action)) {
-                if (Intent.ACTION_LOCALE_CHANGED.equals(action)
-                        || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
-                    // need to get a fresh date format
-                    mHandler.post(KeyguardSliceProvider.this::cleanDateFormat);
-                }
+            if (Intent.ACTION_DATE_CHANGED.equals(action)) {
                 mHandler.post(KeyguardSliceProvider.this::updateClock);
+            } else if (Intent.ACTION_LOCALE_CHANGED.equals(action)) {
+                mHandler.post(KeyguardSliceProvider.this::cleanDateFormat);
             }
         }
     };
 
+    @VisibleForTesting
+    final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback =
+            new KeyguardUpdateMonitorCallback() {
+                @Override
+                public void onTimeChanged() {
+                    mHandler.post(KeyguardSliceProvider.this::updateClock);
+                }
+
+                @Override
+                public void onTimeZoneChanged(TimeZone timeZone) {
+                    mHandler.post(KeyguardSliceProvider.this::cleanDateFormat);
+                }
+            };
+
     public KeyguardSliceProvider() {
         this(new Handler());
     }
@@ -250,11 +260,10 @@
 
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_DATE_CHANGED);
-        filter.addAction(Intent.ACTION_TIME_CHANGED);
-        filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
         filter.addAction(Intent.ACTION_LOCALE_CHANGED);
         getContext().registerReceiver(mIntentReceiver, filter, null /* permission*/,
                 null /* scheduler */);
+        getKeyguardUpdateMonitor().registerCallback(mKeyguardUpdateMonitorCallback);
         mRegistered = true;
     }
 
@@ -300,4 +309,9 @@
         }
         updateNextAlarm();
     }
+
+    @VisibleForTesting
+    protected KeyguardUpdateMonitor getKeyguardUpdateMonitor() {
+        return KeyguardUpdateMonitor.getInstance(getContext());
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 7d1b640..158430f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -19,10 +19,7 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.app.admin.DevicePolicyManager;
-import android.content.BroadcastReceiver;
 import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.graphics.Color;
@@ -35,7 +32,6 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.UserHandle;
 import android.os.UserManager;
 import android.text.TextUtils;
 import android.text.format.Formatter;
@@ -152,10 +148,7 @@
     private void registerCallbacks(KeyguardUpdateMonitor monitor) {
         monitor.registerCallback(getKeyguardCallback());
 
-        mContext.registerReceiverAsUser(mTickReceiver, UserHandle.SYSTEM,
-                new IntentFilter(Intent.ACTION_TIME_TICK), null,
-                Dependency.get(Dependency.TIME_TICK_HANDLER));
-
+        KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mTickReceiver);
         Dependency.get(StatusBarStateController.class).addCallback(this);
     }
 
@@ -166,7 +159,7 @@
      * //TODO: This can probably be converted to a fragment and not have to be manually recreated
      */
     public void destroy() {
-        mContext.unregisterReceiver(mTickReceiver);
+        KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mTickReceiver);
         Dependency.get(StatusBarStateController.class).removeCallback(this);
     }
 
@@ -477,16 +470,15 @@
         mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
     }
 
-    private final BroadcastReceiver mTickReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            mHandler.post(() -> {
-                if (mVisible) {
-                    updateIndication(false);
+    private final KeyguardUpdateMonitorCallback mTickReceiver =
+            new KeyguardUpdateMonitorCallback() {
+                @Override
+                public void onTimeChanged() {
+                    if (mVisible) {
+                        updateIndication(false /* animate */);
+                    }
                 }
-            });
-        }
-    };
+            };
 
     private final Handler mHandler = new Handler() {
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
index 7876aa5..dd07ec4c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.phone;
 
+import static com.android.systemui.statusbar.phone.NavBarTintController.DEFAULT_COLOR_ADAPT_TRANSITION_TIME;
 import static com.android.systemui.statusbar.phone.NavBarTintController.MIN_COLOR_ADAPT_TRANSITION_TIME;
 import static com.android.systemui.statusbar.phone.NavBarTintController.NAV_COLOR_TRANSITION_TIME_SETTING;
 
@@ -161,7 +162,7 @@
     public long getTintAnimationDuration() {
         if (NavBarTintController.isEnabled(mContext)) {
             return Math.max(Settings.Global.getInt(mContext.getContentResolver(),
-                    NAV_COLOR_TRANSITION_TIME_SETTING, DEFAULT_TINT_ANIMATION_DURATION),
+                    NAV_COLOR_TRANSITION_TIME_SETTING, DEFAULT_COLOR_ADAPT_TRANSITION_TIME),
                     MIN_COLOR_ADAPT_TRANSITION_TIME);
         }
         return DEFAULT_TINT_ANIMATION_DURATION;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java
index 9ecee18..b4f850b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java
@@ -31,6 +31,7 @@
 public class NavBarTintController {
     public static final String NAV_COLOR_TRANSITION_TIME_SETTING = "navbar_color_adapt_transition";
     public static final int MIN_COLOR_ADAPT_TRANSITION_TIME = 400;
+    public static final int DEFAULT_COLOR_ADAPT_TRANSITION_TIME = 1500;
 
     private final HandlerThread mColorAdaptHandlerThread = new HandlerThread("ColorExtractThread");
     private Handler mColorAdaptionHandler;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
index c1c80ce..7d94635 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
@@ -19,13 +19,13 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 
 import android.app.AlarmManager;
 import android.content.ContentResolver;
-import android.content.Intent;
 import android.net.Uri;
 import android.provider.Settings;
 import android.support.test.filters.SmallTest;
@@ -40,6 +40,7 @@
 import androidx.slice.builders.ListBuilder;
 import androidx.slice.core.SliceQuery;
 
+import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.SysuiTestCase;
 
 import org.junit.Assert;
@@ -91,7 +92,7 @@
 
     @Test
     public void cleansDateFormat() {
-        mProvider.mIntentReceiver.onReceive(getContext(), new Intent(Intent.ACTION_TIMEZONE_CHANGED));
+        mProvider.mKeyguardUpdateMonitorCallback.onTimeZoneChanged(null);
         TestableLooper.get(this).processAllMessages();
         Assert.assertEquals("Date format should have been cleaned.", 1 /* expected */,
                 mProvider.mCleanDateFormatInvokations);
@@ -99,7 +100,7 @@
 
     @Test
     public void updatesClock() {
-        mProvider.mIntentReceiver.onReceive(getContext(), new Intent(Intent.ACTION_TIME_TICK));
+        mProvider.mKeyguardUpdateMonitorCallback.onTimeChanged();
         TestableLooper.get(this).processAllMessages();
         verify(mContentResolver).notifyChange(eq(mProvider.getUri()), eq(null));
     }
@@ -171,6 +172,11 @@
         }
 
         @Override
+        public KeyguardUpdateMonitor getKeyguardUpdateMonitor() {
+            return mock(KeyguardUpdateMonitor.class);
+        }
+
+        @Override
         protected String getFormattedDate() {
             return super.getFormattedDate() + mCounter++;
         }
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index 8ec97c5..d0937e9 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -1519,6 +1519,13 @@
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+                // Stacks and activities could be removed while putting activities to sleep if
+                // the app process was gone. This prevents us getting exception by accessing an
+                // invalid stack index.
+                if (stackNdx >= display.getChildCount()) {
+                    continue;
+                }
+
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 if (allowDelay) {
                     allSleep &= stack.goToSleepIfPossible(shuttingDown);
diff --git a/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
index c006a7b..b219419 100644
--- a/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
+++ b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
@@ -66,8 +66,11 @@
                     // method target window will lose the focus.
                     return;
                 }
-                mDisplayContent.getParent().positionChildAt(WindowContainer.POSITION_TOP,
-                        mDisplayContent, true /* includingParents */);
+                WindowContainer parent = mDisplayContent.getParent();
+                if (parent != null) {
+                    parent.positionChildAt(WindowContainer.POSITION_TOP, mDisplayContent,
+                            true /* includingParents */);
+                }
             }
         };
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
index 83e7ee7..dfdbf32 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
@@ -49,12 +49,9 @@
 import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
 
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
 
 import java.util.concurrent.CountDownLatch;
 
@@ -72,7 +69,6 @@
     @Mock Transaction mMockTransaction;
     @Mock AnimationSpec mMockAnimationSpec;
     @Mock PowerManagerInternal mMockPowerManager;
-    @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
 
     private SurfaceAnimationRunner mSurfaceAnimationRunner;
     private CountDownLatch mFinishCallbackLatch;
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index 1cbe5a2..c115a4b 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -2732,10 +2732,26 @@
 
         /**
          * The {@code content://} style URL for this table.
+         * For MSIM, this will return APNs for the default subscription
+         * {@link SubscriptionManager#getDefaultSubscriptionId()}. To specify subId for MSIM,
+         * use {@link Uri#withAppendedPath(Uri, String)} to append with subscription id.
          */
         public static final Uri CONTENT_URI = Uri.parse("content://telephony/carriers");
 
         /**
+         * The {@code content://} style URL for this table. Used for APN query based on current
+         * subscription. Instead of specifying carrier matching information in the selection,
+         * this API will return all matching APNs from current subscription carrier and queries
+         * will be applied on top of that. If there is no match for MVNO (Mobile Virtual Network
+         * Operator) APNs, return APNs from its MNO (based on mccmnc) instead. For MSIM, this will
+         * return APNs for the default subscription
+         * {@link SubscriptionManager#getDefaultSubscriptionId()}. To specify subId for MSIM,
+         * use {@link Uri#withAppendedPath(Uri, String)} to append with subscription id.
+         */
+        public static final Uri SIM_APN_URI = Uri.parse(
+                "content://telephony/carriers/sim_apn_list");
+
+        /**
          * The {@code content://} style URL to be called from DevicePolicyManagerService,
          * can manage DPC-owned APNs.
          * @hide
@@ -2745,7 +2761,9 @@
         /**
          * The {@code content://} style URL to be called from Telephony to query APNs.
          * When DPC-owned APNs are enforced, only DPC-owned APNs are returned, otherwise only
-         * non-DPC-owned APNs are returned.
+         * non-DPC-owned APNs are returned. For MSIM, this will return APNs for the default
+         * subscription {@link SubscriptionManager#getDefaultSubscriptionId()}. To specify subId
+         * for MSIM, use {@link Uri#withAppendedPath(Uri, String)} to append with subscription id.
          * @hide
          */
         public static final Uri FILTERED_URI = Uri.parse("content://telephony/carriers/filtered");
@@ -2759,13 +2777,6 @@
                 "content://telephony/carriers/enforce_managed");
 
         /**
-         * The {@code content://} style URL to be called from Telephony to query current APNs.
-         * @hide
-         */
-        public static final Uri SIM_APN_LIST = Uri.parse(
-                "content://telephony/carriers/sim_apn_list");
-
-        /**
          * The column name for ENFORCE_MANAGED_URI, indicates whether DPC-owned APNs are enforced.
          * @hide
          */
@@ -2839,18 +2850,30 @@
         /**
          * Mobile Country Code (MCC).
          * <P>Type: TEXT</P>
+         * @deprecated Use {@link #SIM_APN_URI} to query APN instead, this API will return
+         * matching APNs based on current subscription carrier, thus no need to specify MCC and
+         * other carrier matching information. In the future, Android will not support MCC for
+         * APN query.
          */
         public static final String MCC = "mcc";
 
         /**
          * Mobile Network Code (MNC).
          * <P>Type: TEXT</P>
+         * @deprecated Use {@link #SIM_APN_URI} to query APN instead, this API will return
+         * matching APNs based on current subscription carrier, thus no need to specify MNC and
+         * other carrier matching information. In the future, Android will not support MNC for
+         * APN query.
          */
         public static final String MNC = "mnc";
 
         /**
          * Numeric operator ID (as String). Usually {@code MCC + MNC}.
          * <P>Type: TEXT</P>
+         * @deprecated Use {@link #SIM_APN_URI} to query APN instead, this API will return
+         * matching APNs based on current subscription carrier, thus no need to specify Numeric
+         * and other carrier matching information. In the future, Android will not support Numeric
+         * for APN query.
          */
         public static final String NUMERIC = "numeric";
 
@@ -2931,6 +2954,10 @@
          * MVNO type:
          * {@code SPN (Service Provider Name), IMSI, GID (Group Identifier Level 1)}.
          * <P>Type: TEXT</P>
+         * @deprecated Use {@link #SIM_APN_URI} to query APN instead, this API will return
+         * matching APNs based on current subscription carrier, thus no need to specify MVNO_TYPE
+         * and other carrier matching information. In the future, Android will not support MVNO_TYPE
+         * for APN query.
          */
         public static final String MVNO_TYPE = "mvno_type";
 
@@ -2943,6 +2970,10 @@
          *     <li>GID: 4E, 33, ...</li>
          * </ul>
          * <P>Type: TEXT</P>
+         * @deprecated Use {@link #SIM_APN_URI} to query APN instead, this API will return
+         * matching APNs based on current subscription carrier, thus no need to specify
+         * MVNO_MATCH_DATA and other carrier matching information. In the future, Android will not
+         * support MVNO_MATCH_DATA for APN query.
          */
         public static final String MVNO_MATCH_DATA = "mvno_match_data";
 
@@ -3151,7 +3182,6 @@
         })
         @Retention(RetentionPolicy.SOURCE)
         public @interface EditStatus {}
-
     }
 
     /**
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index 355a576..6326cc6 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -61,7 +61,6 @@
     public static final String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS =
             "android.telephony.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS";
 
-
     /**
      * Broadcast Action: The eUICC OTA status is changed.
      * <p class="note">
@@ -87,6 +86,20 @@
             "android.telephony.euicc.action.NOTIFY_CARRIER_SETUP_INCOMPLETE";
 
     /**
+     * Intent action to select a profile to enable before download a new eSIM profile.
+     *
+     * May be called during device provisioning when there are multiple slots having profiles on
+     * them. This Intent launches a screen for all the current existing profiles and let users to
+     * choose which one they want to enable. In this case, the slot contains the profile will be
+     * activated.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String ACTION_PROFILE_SELECTION =
+            "android.telephony.euicc.action.PROFILE_SELECTION";
+
+    /**
      * Intent action to provision an embedded subscription.
      *
      * <p>May be called during device provisioning to launch a screen to perform embedded SIM
@@ -132,6 +145,16 @@
     public static final int EMBEDDED_SUBSCRIPTION_RESULT_ERROR = 2;
 
     /**
+     * Key for an extra set on the {@link #ACTION_PROVISION_EMBEDDED_SUBSCRIPTION} intent for which
+     * kind of activation flow will be evolved. (see {@code EUICC_ACTIVATION_})
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_ACTIVATION_TYPE =
+            "android.telephony.euicc.extra.ACTIVATION_TYPE";
+
+    /**
      * Key for an extra set on {@link PendingIntent} result callbacks providing a detailed result
      * code.
      *
@@ -197,6 +220,52 @@
     public static final String META_DATA_CARRIER_ICON = "android.telephony.euicc.carriericon";
 
     /**
+     * Euicc activation type which will be included in {@link #EXTRA_ACTIVATION_TYPE} and used to
+     * decide which kind of activation flow should be lauched.
+     *
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"EUICC_ACTIVATION_"}, value = {
+            EUICC_ACTIVATION_TYPE_DEFAULT,
+            EUICC_ACTIVATION_TYPE_BACKUP,
+            EUICC_ACTIVATION_TYPE_TRANSFER
+
+    })
+    public @interface EuiccActivationType{}
+
+
+    /**
+     * The default euicc activation type which includes checking server side and downloading the
+     * profile based on carrier's download configuration.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int EUICC_ACTIVATION_TYPE_DEFAULT = 1;
+
+    /**
+     * The euicc activation type used when the default download process failed. LPA will start the
+     * backup flow and try to download the profile for the carrier.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int EUICC_ACTIVATION_TYPE_BACKUP = 2;
+
+    /**
+     * The activation flow of eSIM seamless transfer will be used. LPA will start normal eSIM
+     * activation flow and if it's failed, the name of the carrier selected will be recorded. After
+     * the future device pairing, LPA will contact this carrier to transfer it from the other device
+     * to this device.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int EUICC_ACTIVATION_TYPE_TRANSFER = 3;
+
+
+    /**
      * Euicc OTA update status which can be got by {@link #getOtaStatus}
      * @hide
      */