Merge "Import translations. DO NOT MERGE"
diff --git a/Android.mk b/Android.mk
index 7ca8358..10d11f3 100644
--- a/Android.mk
+++ b/Android.mk
@@ -656,6 +656,10 @@
 # Check comment when you are updating the API
 update-api: doc-comment-check-docs
 
+# Generate API diffs as part of docs builds
+docs: offline-sdk-referenceonly-diff
+docs: offline-system-sdk-referenceonly-diff
+
 # ====  static html in the sdk ==================================
 include $(CLEAR_VARS)
 
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index 87cde03..337aeaa 100644
--- a/cmds/statsd/Android.mk
+++ b/cmds/statsd/Android.mk
@@ -161,6 +161,7 @@
     tests/LogEntryMatcher_test.cpp \
     tests/LogReader_test.cpp \
     tests/MetricsManager_test.cpp \
+    tests/StatsLogProcessor_test.cpp \
     tests/UidMap_test.cpp \
     tests/condition/CombinationConditionTracker_test.cpp \
     tests/condition/SimpleConditionTracker_test.cpp \
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index c291647..2df0c90 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -86,9 +86,7 @@
     // pass the event to metrics managers.
     for (auto& pair : mMetricsManagers) {
         pair.second->onLogEvent(msg);
-        // TODO: THIS CHECK FAILS BECAUSE ONCE UIDMAP SIZE EXCEEDS LIMIT, DROPPING METRICS DATA
-        // DOESN'T HELP. FIX THIS.
-        // flushIfNecessary(msg.GetTimestampNs(), pair.first, pair.second);
+        flushIfNecessary(msg.GetTimestampNs(), pair.first, *(pair.second));
     }
 
     // Hard-coded logic to update the isolated uid's in the uid-map.
@@ -217,23 +215,32 @@
     mLastBroadcastTimes.erase(key);
 }
 
-void StatsLogProcessor::flushIfNecessary(uint64_t timestampNs,
-                                         const ConfigKey& key,
-                                         const unique_ptr<MetricsManager>& metricsManager) {
+void StatsLogProcessor::flushIfNecessary(uint64_t timestampNs, const ConfigKey& key,
+                                         MetricsManager& metricsManager) {
     std::lock_guard<std::mutex> lock(mBroadcastTimesMutex);
 
-    size_t totalBytes = metricsManager->byteSize() + mUidMap->getBytesUsed();
-    // TODO: Find a way to test that the dropping and broadcasts are sent when memory is exceeded.
-    if (totalBytes > kMaxSerializedBytes) {  // Too late. We need to start clearing data.
+    auto lastCheckTime = mLastByteSizeTimes.find(key);
+    if (lastCheckTime != mLastByteSizeTimes.end()) {
+        if (timestampNs - lastCheckTime->second < StatsdStats::kMinByteSizeCheckPeriodNs) {
+            return;
+        }
+    }
+
+    // We suspect that the byteSize() computation is expensive, so we set a rate limit.
+    size_t totalBytes = metricsManager.byteSize();
+    mLastByteSizeTimes[key] = timestampNs;
+    if (totalBytes >
+        StatsdStats::kMaxMetricsBytesPerConfig) {  // Too late. We need to start clearing data.
         // We ignore the return value so we force each metric producer to clear its contents.
-        metricsManager->onDumpReport();
+        metricsManager.onDumpReport();
         StatsdStats::getInstance().noteDataDropped(key);
         VLOG("StatsD had to toss out metrics for %s", key.ToString().c_str());
-    } else if (totalBytes >
-               .9 * kMaxSerializedBytes) {  // Send broadcast so that receivers can pull data.
-        auto lastFlushNs = mLastBroadcastTimes.find(key);
-        if (lastFlushNs != mLastBroadcastTimes.end()) {
-            if (timestampNs - lastFlushNs->second < kMinBroadcastPeriod) {
+    } else if (totalBytes > .9 * StatsdStats::kMaxMetricsBytesPerConfig) {
+        // Send broadcast so that receivers can pull data.
+        auto lastBroadcastTime = mLastBroadcastTimes.find(key);
+        if (lastBroadcastTime != mLastBroadcastTimes.end()) {
+            if (timestampNs - lastBroadcastTime->second < StatsdStats::kMinBroadcastPeriodNs) {
+                VLOG("StatsD would've sent a broadcast but the rate limit stopped us.");
                 return;
             }
         }
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index e9ac015..a4df23a 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -60,29 +60,25 @@
 
     std::unordered_map<ConfigKey, long> mLastBroadcastTimes;
 
+    // Tracks when we last checked the bytes consumed for each config key.
+    std::unordered_map<ConfigKey, long> mLastByteSizeTimes;
+
     sp<UidMap> mUidMap;  // Reference to the UidMap to lookup app name and version for each uid.
 
     sp<AnomalyMonitor> mAnomalyMonitor;
 
-    /* Max *serialized* size of the logs kept in memory before flushing through binder call.
-       Proto lite does not implement the SpaceUsed() function which gives the in memory byte size.
-       So we cap memory usage by limiting the serialized size. Note that protobuf's in memory size
-       is higher than its serialized size.
-     */
-    static const size_t kMaxSerializedBytes = 16 * 1024;
-
     /* Check if we should send a broadcast if approaching memory limits and if we're over, we
      * actually delete the data. */
-    void flushIfNecessary(uint64_t timestampNs,
-                          const ConfigKey& key,
-                          const unique_ptr<MetricsManager>& metricsManager);
+    void flushIfNecessary(uint64_t timestampNs, const ConfigKey& key,
+                          MetricsManager& metricsManager);
 
     // Function used to send a broadcast so that receiver for the config key can call getData
     // to retrieve the stored data.
     std::function<void(const ConfigKey& key)> mSendBroadcast;
 
-    /* Minimum period between two broadcasts in nanoseconds. Currently set to 60 seconds. */
-    static const unsigned long long kMinBroadcastPeriod = 60 * NS_PER_SEC;
+    FRIEND_TEST(StatsLogProcessorTest, TestRateLimitByteSize);
+    FRIEND_TEST(StatsLogProcessorTest, TestRateLimitBroadcast);
+    FRIEND_TEST(StatsLogProcessorTest, TestDropWhenByteSizeTooLarge);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index fa7fe0c..dc12efb 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -72,7 +72,7 @@
 
 // ======================================================================
 StatsService::StatsService(const sp<Looper>& handlerLooper)
-    : mAnomalyMonitor(new AnomalyMonitor(2))  // TODO: Put this comment somewhere better
+    : mAnomalyMonitor(new AnomalyMonitor(MIN_DIFF_TO_UPDATE_REGISTERED_ALARM_SECS))
 {
     mUidMap = new UidMap();
     mConfigManager = new ConfigManager();
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index bdae1ef..e434f65 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -46,6 +46,10 @@
     StatsService(const sp<Looper>& handlerLooper);
     virtual ~StatsService();
 
+    /** The anomaly alarm registered with AlarmManager won't be updated by less than this. */
+    // TODO: Consider making this configurable. And choose a good number.
+    const uint32_t MIN_DIFF_TO_UPDATE_REGISTERED_ALARM_SECS = 5;
+
     virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
     virtual status_t dump(int fd, const Vector<String16>& args);
     virtual status_t command(FILE* in, FILE* out, FILE* err, Vector<String8>& args);
diff --git a/cmds/statsd/src/anomaly/AnomalyMonitor.cpp b/cmds/statsd/src/anomaly/AnomalyMonitor.cpp
index 2b2bcfc..4912648 100644
--- a/cmds/statsd/src/anomaly/AnomalyMonitor.cpp
+++ b/cmds/statsd/src/anomaly/AnomalyMonitor.cpp
@@ -18,6 +18,7 @@
 #include "Log.h"
 
 #include "anomaly/AnomalyMonitor.h"
+#include "guardrail/StatsdStats.h"
 
 namespace android {
 namespace os {
@@ -76,10 +77,7 @@
     if (!wasPresent) return;
     if (mPq.empty()) {
         if (DEBUG) ALOGD("Queue is empty. Cancel any alarm.");
-        mRegisteredAlarmTimeSec = 0;
-        if (mStatsCompanionService != nullptr) {
-            mStatsCompanionService->cancelAnomalyAlarm();
-        }
+        cancelRegisteredAlarmTime_l();
         return;
     }
     uint32_t soonestAlarmTimeSec = mPq.top()->timestampSec;
@@ -106,10 +104,7 @@
     if (!oldAlarms.empty()) {
         if (mPq.empty()) {
             if (DEBUG) ALOGD("Queue is empty. Cancel any alarm.");
-            mRegisteredAlarmTimeSec = 0;
-            if (mStatsCompanionService != nullptr) {
-                mStatsCompanionService->cancelAnomalyAlarm();
-            }
+            cancelRegisteredAlarmTime_l();
         } else {
             // Always update the registered alarm in this case (unlike remove()).
             updateRegisteredAlarmTime_l(mPq.top()->timestampSec);
@@ -123,6 +118,16 @@
     mRegisteredAlarmTimeSec = timestampSec;
     if (mStatsCompanionService != nullptr) {
         mStatsCompanionService->setAnomalyAlarm(secToMs(mRegisteredAlarmTimeSec));
+        StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged();
+    }
+}
+
+void AnomalyMonitor::cancelRegisteredAlarmTime_l() {
+    if (DEBUG) ALOGD("Cancelling reg alarm.");
+    mRegisteredAlarmTimeSec = 0;
+    if (mStatsCompanionService != nullptr) {
+        mStatsCompanionService->cancelAnomalyAlarm();
+        StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged();
     }
 }
 
diff --git a/cmds/statsd/src/anomaly/AnomalyMonitor.h b/cmds/statsd/src/anomaly/AnomalyMonitor.h
index e19c469..7acc7904 100644
--- a/cmds/statsd/src/anomaly/AnomalyMonitor.h
+++ b/cmds/statsd/src/anomaly/AnomalyMonitor.h
@@ -138,6 +138,12 @@
      */
     void updateRegisteredAlarmTime_l(uint32_t timestampSec);
 
+    /**
+     * Cancels the alarm registered with StatsCompanionService.
+     * Also correspondingly sets mRegisteredAlarmTimeSec to 0.
+     */
+    void cancelRegisteredAlarmTime_l();
+
     /** Converts uint32 timestamp in seconds to a Java long in msec. */
     int64_t secToMs(uint32_t timeSec);
 };
diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.cpp b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
index 7bacb44..e8b4083 100644
--- a/cmds/statsd/src/anomaly/AnomalyTracker.cpp
+++ b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
@@ -18,6 +18,7 @@
 #include "Log.h"
 
 #include "AnomalyTracker.h"
+#include "guardrail/StatsdStats.h"
 
 #include <android/os/IIncidentManager.h>
 #include <android/os/IncidentReportArgs.h>
@@ -31,8 +32,9 @@
 // TODO: Separate DurationAnomalyTracker as a separate subclass and let each MetricProducer
 //       decide and let which one it wants.
 // TODO: Get rid of bucketNumbers, and return to the original circular array method.
-AnomalyTracker::AnomalyTracker(const Alert& alert)
+AnomalyTracker::AnomalyTracker(const Alert& alert, const ConfigKey& configKey)
     : mAlert(alert),
+      mConfigKey(configKey),
       mNumOfPastBuckets(mAlert.number_of_buckets() - 1) {
     VLOG("AnomalyTracker() called");
     if (mAlert.number_of_buckets() <= 0) {
@@ -220,6 +222,8 @@
     } else {
         ALOGW("An anomaly has occurred! (But informing incidentd not requested.)");
     }
+
+    StatsdStats::getInstance().noteAnomalyDeclared(mConfigKey, mAlert.name());
 }
 
 void AnomalyTracker::declareAnomalyIfAlarmExpired(const HashableDimensionKey& dimensionKey,
diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.h b/cmds/statsd/src/anomaly/AnomalyTracker.h
index 49e8323..874add2 100644
--- a/cmds/statsd/src/anomaly/AnomalyTracker.h
+++ b/cmds/statsd/src/anomaly/AnomalyTracker.h
@@ -18,6 +18,7 @@
 
 #include <gtest/gtest_prod.h>
 #include "AnomalyMonitor.h"
+#include "config/ConfigKey.h"
 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"  // Alert
 #include "stats_util.h"  // HashableDimensionKey and DimToValMap
 
@@ -35,7 +36,7 @@
 // Does NOT allow negative values.
 class AnomalyTracker : public virtual RefBase {
 public:
-    AnomalyTracker(const Alert& alert);
+    AnomalyTracker(const Alert& alert, const ConfigKey& configKey);
 
     virtual ~AnomalyTracker();
 
@@ -107,9 +108,13 @@
 
 protected:
     void flushPastBuckets(const int64_t& currBucketNum);
+
     // statsd_config.proto Alert message that defines this tracker.
     const Alert mAlert;
 
+    // A reference to the Alert's config key.
+    const ConfigKey& mConfigKey;
+
     // Number of past buckets. One less than the total number of buckets needed
     // for the anomaly detection (since the current bucket is not in the past).
     int mNumOfPastBuckets;
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index 2957457..b02b9da 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -41,11 +41,9 @@
 const int FIELD_ID_BEGIN_TIME = 1;
 const int FIELD_ID_END_TIME = 2;
 const int FIELD_ID_CONFIG_STATS = 3;
-const int FIELD_ID_MATCHER_STATS = 4;
-const int FIELD_ID_CONDITION_STATS = 5;
-const int FIELD_ID_METRIC_STATS = 6;
 const int FIELD_ID_ATOM_STATS = 7;
 const int FIELD_ID_UIDMAP_STATS = 8;
+const int FIELD_ID_ANOMALY_ALARM_STATS = 9;
 
 const int FIELD_ID_MATCHER_STATS_NAME = 1;
 const int FIELD_ID_MATCHER_STATS_COUNT = 2;
@@ -59,6 +57,8 @@
 const int FIELD_ID_ATOM_STATS_TAG = 1;
 const int FIELD_ID_ATOM_STATS_COUNT = 2;
 
+const int FIELD_ID_ANOMALY_ALARMS_REGISTERED = 1;
+
 // TODO: add stats for pulled atoms.
 StatsdStats::StatsdStats() {
     mPushedAtomStats.resize(android::util::kMaxPushedAtomId + 1);
@@ -101,11 +101,12 @@
     if (it != mConfigStats.end()) {
         int32_t nowTimeSec = time(nullptr);
         it->second.set_deletion_time_sec(nowTimeSec);
-        // Add condition stats, metrics stats, matcher stats
-        addSubStatsToConfig(key, it->second);
+        // Add condition stats, metrics stats, matcher stats, alert stats
+        addSubStatsToConfigLocked(key, it->second);
         // Remove them after they are added to the config stats.
         mMatcherStats.erase(key);
         mMetricsStats.erase(key);
+        mAlertStats.erase(key);
         mConditionStats.erase(key);
         mIceBox.push_back(it->second);
         mConfigStats.erase(it);
@@ -219,6 +220,17 @@
     matcherStats[name]++;
 }
 
+void StatsdStats::noteAnomalyDeclared(const ConfigKey& key, const string& name) {
+    lock_guard<std::mutex> lock(mLock);
+    auto& alertStats = mAlertStats[key];
+    alertStats[name]++;
+}
+
+void StatsdStats::noteRegisteredAnomalyAlarmChanged() {
+    lock_guard<std::mutex> lock(mLock);
+    mAnomalyAlarmRegisteredStats++;
+}
+
 void StatsdStats::noteAtomLogged(int atomId, int32_t timeSec) {
     lock_guard<std::mutex> lock(mLock);
 
@@ -246,6 +258,8 @@
     mConditionStats.clear();
     mMetricsStats.clear();
     std::fill(mPushedAtomStats.begin(), mPushedAtomStats.end(), 0);
+    mAlertStats.clear();
+    mAnomalyAlarmRegisteredStats = 0;
     mMatcherStats.clear();
     for (auto& config : mConfigStats) {
         config.second.clear_broadcast_sent_time_sec();
@@ -254,10 +268,11 @@
         config.second.clear_matcher_stats();
         config.second.clear_condition_stats();
         config.second.clear_metric_stats();
+        config.second.clear_alert_stats();
     }
 }
 
-void StatsdStats::addSubStatsToConfig(const ConfigKey& key,
+void StatsdStats::addSubStatsToConfigLocked(const ConfigKey& key,
                                       StatsdStatsReport_ConfigStats& configStats) {
     // Add matcher stats
     if (mMatcherStats.find(key) != mMatcherStats.end()) {
@@ -289,6 +304,16 @@
             VLOG("metrics %s max output tuple size %d", stats.first.c_str(), stats.second);
         }
     }
+    // Add anomaly detection alert stats
+    if (mAlertStats.find(key) != mAlertStats.end()) {
+        const auto& alertStats = mAlertStats[key];
+        for (const auto& stats : alertStats) {
+            auto output = configStats.add_alert_stats();
+            output->set_name(stats.first);
+            output->set_declared_times(stats.second);
+            VLOG("alert %s declared %d times", stats.first.c_str(), stats.second);
+        }
+    }
 }
 
 void StatsdStats::dumpStats(std::vector<uint8_t>* output, bool reset) {
@@ -358,7 +383,7 @@
             }
         }
 
-        addSubStatsToConfig(pair.first, configStats);
+        addSubStatsToConfigLocked(pair.first, configStats);
 
         const int numBytes = configStats.ByteSize();
         vector<char> buffer(numBytes);
@@ -370,6 +395,7 @@
         configStats.clear_matcher_stats();
         configStats.clear_condition_stats();
         configStats.clear_metric_stats();
+        configStats.clear_alert_stats();
     }
 
     VLOG("********Atom stats***********");
@@ -386,6 +412,15 @@
         }
     }
 
+    if (mAnomalyAlarmRegisteredStats > 0) {
+        VLOG("********AnomalyAlarmStats stats***********");
+        long long token = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_ANOMALY_ALARM_STATS);
+        proto.write(FIELD_TYPE_INT32 | FIELD_ID_ANOMALY_ALARMS_REGISTERED,
+                    mAnomalyAlarmRegisteredStats);
+        proto.end(token);
+        VLOG("Anomaly alarm registrations: %d", mAnomalyAlarmRegisteredStats);
+    }
+
     const int numBytes = mUidMapStats.ByteSize();
     vector<char> buffer(numBytes);
     mUidMapStats.SerializeToArray(&buffer[0], numBytes);
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index d6f6566..4cf168e 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -19,6 +19,7 @@
 #include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
 
 #include <gtest/gtest_prod.h>
+#include <log/log_time.h>
 #include <mutex>
 #include <string>
 #include <vector>
@@ -45,10 +46,20 @@
 
     const static int kMaxTimestampCount = 20;
 
+    // Max memory allowed for storing metrics per configuration. When this limit is approached,
+    // statsd will send a broadcast so that the client can fetch the data and clear this memory.
+    static const size_t kMaxMetricsBytesPerConfig = 128 * 1024;
+
     // Cap the UID map's memory usage to this. This should be fairly high since the UID information
     // is critical for understanding the metrics.
     const static size_t kMaxBytesUsedUidMap = 50 * 1024;
 
+    /* Minimum period between two broadcasts in nanoseconds. */
+    static const unsigned long long kMinBroadcastPeriodNs = 60 * NS_PER_SEC;
+
+    /* Min period between two checks of byte size per config key in nanoseconds. */
+    static const unsigned long long kMinByteSizeCheckPeriodNs = 10 * NS_PER_SEC;
+
     /**
      * Report a new config has been received and report the static stats about the config.
      *
@@ -112,11 +123,24 @@
     void noteMatcherMatched(const ConfigKey& key, const std::string& name);
 
     /**
+     * Report that an anomaly detection alert has been declared.
+     *
+     * [key]: The config key that this alert belongs to.
+     * [name]: The name of the alert.
+     */
+    void noteAnomalyDeclared(const ConfigKey& key, const std::string& name);
+
+    /**
      * Report an atom event has been logged.
      */
     void noteAtomLogged(int atomId, int32_t timeSec);
 
     /**
+     * Report that statsd modified the anomaly alarm registered with StatsCompanionService.
+     */
+    void noteRegisteredAnomalyAlarmChanged();
+
+    /**
      * Records the number of snapshot and delta entries that are being dropped from the uid map.
      */
     void noteUidMapDropped(int snapshots, int deltas);
@@ -174,6 +198,14 @@
     // This is a vector, not a map because it will be accessed A LOT -- for each stats log.
     std::vector<int> mPushedAtomStats;
 
+    // Stores the number of times statsd modified the anomaly alarm registered with
+    // StatsCompanionService.
+    int mAnomalyAlarmRegisteredStats = 0;
+
+    // Stores the number of times an anomaly detection alert has been declared
+    // (per config, per alert name).
+    std::map<const ConfigKey, std::map<const std::string, int>> mAlertStats;
+
     // Stores how many times a matcher have been matched.
     std::map<const ConfigKey, std::map<const std::string, int>> mMatcherStats;
 
@@ -181,7 +213,8 @@
 
     void resetInternalLocked();
 
-    void addSubStatsToConfig(const ConfigKey& key, StatsdStatsReport_ConfigStats& configStats);
+    void addSubStatsToConfigLocked(const ConfigKey& key,
+                                   StatsdStatsReport_ConfigStats& configStats);
 
     void noteDataDropped(const ConfigKey& key, int32_t timeSec);
 
@@ -195,6 +228,7 @@
     FRIEND_TEST(StatsdStatsTest, TestSubStats);
     FRIEND_TEST(StatsdStatsTest, TestAtomLog);
     FRIEND_TEST(StatsdStatsTest, TestTimestampThreshold);
+    FRIEND_TEST(StatsdStatsTest, TestAnomalyMonitor);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index fd484c2..cedea30 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -111,7 +111,7 @@
         return nullptr;
     }
     // TODO: return a DurationAnomalyTracker (which should sublclass AnomalyTracker)
-    return new AnomalyTracker(alert);
+    return new AnomalyTracker(alert, mConfigKey);
 }
 
 void DurationMetricProducer::startNewProtoOutputStreamLocked(long long startTime) {
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index e7e84ab..adeb3cd 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -94,7 +94,7 @@
     }
 
     virtual sp<AnomalyTracker> createAnomalyTracker(const Alert &alert) {
-        return new AnomalyTracker(alert);
+        return new AnomalyTracker(alert, mConfigKey);
     }
 
     void addAnomalyTracker(sp<AnomalyTracker> tracker) {
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index 4e6a0ce..86c4733 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -36,7 +36,7 @@
 public:
     MetricsManager(const ConfigKey& configKey, const StatsdConfig& config);
 
-    ~MetricsManager();
+    virtual ~MetricsManager();
 
     // Return whether the configuration is valid.
     bool isConfigValid() const;
@@ -52,11 +52,11 @@
     void setAnomalyMonitor(const sp<AnomalyMonitor>& anomalyMonitor);
 
     // Config source owner can call onDumpReport() to get all the metrics collected.
-    std::vector<std::unique_ptr<std::vector<uint8_t>>> onDumpReport();
+    virtual std::vector<std::unique_ptr<std::vector<uint8_t>>> onDumpReport();
 
     // Computes the total byte size of all metrics managed by a single config source.
     // Does not change the state.
-    size_t byteSize();
+    virtual size_t byteSize();
 
 private:
     const ConfigKey mConfigKey;
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 60d9a3d..f8b91fe 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -193,6 +193,11 @@
         optional int32 max_tuple_counts = 2;
     }
 
+    message AlertStats {
+        optional string name = 1;
+        optional int32 declared_times = 2;
+    }
+
     message ConfigStats {
         optional int32 uid = 1;
         optional string name = 2;
@@ -210,6 +215,7 @@
         repeated MatcherStats matcher_stats = 13;
         repeated ConditionStats condition_stats = 14;
         repeated MetricStats metric_stats = 15;
+        repeated AlertStats alert_stats = 16;
     }
 
     repeated ConfigStats config_stats = 3;
@@ -229,4 +235,9 @@
         optional int32 dropped_changes = 5;
     }
     optional UidMapStats uidmap_stats = 8;
+
+    message AnomalyAlarmStats {
+        optional int32 alarms_registered = 1;
+    }
+    optional AnomalyAlarmStats anomaly_alarm_stats = 9;
 }
\ No newline at end of file
diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp
new file mode 100644
index 0000000..ff04d95
--- /dev/null
+++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp
@@ -0,0 +1,117 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "StatsLogProcessor.h"
+#include "config/ConfigKey.h"
+#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
+#include "guardrail/StatsdStats.h"
+#include "logd/LogEvent.h"
+#include "packages/UidMap.h"
+#include "statslog.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <stdio.h>
+
+using namespace android;
+using namespace testing;
+
+namespace android {
+namespace os {
+namespace statsd {
+
+#ifdef __ANDROID__
+
+/**
+ * Mock MetricsManager (ByteSize() is called).
+ */
+class MockMetricsManager : public MetricsManager {
+public:
+    MockMetricsManager() : MetricsManager(ConfigKey(1, "key"), StatsdConfig()) {
+    }
+
+    MOCK_METHOD0(byteSize, size_t());
+    MOCK_METHOD0(onDumpReport, std::vector<std::unique_ptr<std::vector<uint8_t>>>());
+};
+
+TEST(StatsLogProcessorTest, TestRateLimitByteSize) {
+    sp<UidMap> m = new UidMap();
+    sp<AnomalyMonitor> anomalyMonitor;
+    // Construct the processor with a dummy sendBroadcast function that does nothing.
+    StatsLogProcessor p(m, anomalyMonitor, [](const ConfigKey& key) {});
+
+    MockMetricsManager mockMetricsManager;
+
+    ConfigKey key(100, "key");
+    // Expect only the first flush to trigger a check for byte size since the last two are
+    // rate-limited.
+    EXPECT_CALL(mockMetricsManager, byteSize()).Times(1);
+    p.flushIfNecessary(99, key, mockMetricsManager);
+    p.flushIfNecessary(100, key, mockMetricsManager);
+    p.flushIfNecessary(101, key, mockMetricsManager);
+}
+
+TEST(StatsLogProcessorTest, TestRateLimitBroadcast) {
+    sp<UidMap> m = new UidMap();
+    sp<AnomalyMonitor> anomalyMonitor;
+    int broadcastCount = 0;
+    StatsLogProcessor p(m, anomalyMonitor,
+                        [&broadcastCount](const ConfigKey& key) { broadcastCount++; });
+
+    MockMetricsManager mockMetricsManager;
+
+    ConfigKey key(100, "key");
+    EXPECT_CALL(mockMetricsManager, byteSize())
+            .Times(2)
+            .WillRepeatedly(Return(int(StatsdStats::kMaxMetricsBytesPerConfig * .95)));
+
+    // Expect only one broadcast despite always returning a size that should trigger broadcast.
+    p.flushIfNecessary(1, key, mockMetricsManager);
+    EXPECT_EQ(1, broadcastCount);
+
+    // This next call to flush should not trigger a broadcast.
+    p.mLastByteSizeTimes.clear();  // Force another check for byte size.
+    p.flushIfNecessary(2, key, mockMetricsManager);
+    EXPECT_EQ(1, broadcastCount);
+}
+
+TEST(StatsLogProcessorTest, TestDropWhenByteSizeTooLarge) {
+    sp<UidMap> m = new UidMap();
+    sp<AnomalyMonitor> anomalyMonitor;
+    int broadcastCount = 0;
+    StatsLogProcessor p(m, anomalyMonitor,
+                        [&broadcastCount](const ConfigKey& key) { broadcastCount++; });
+
+    MockMetricsManager mockMetricsManager;
+
+    ConfigKey key(100, "key");
+    EXPECT_CALL(mockMetricsManager, byteSize())
+            .Times(1)
+            .WillRepeatedly(Return(int(StatsdStats::kMaxMetricsBytesPerConfig * 1.2)));
+
+    EXPECT_CALL(mockMetricsManager, onDumpReport()).Times(1);
+
+    // Expect to call the onDumpReport and skip the broadcast.
+    p.flushIfNecessary(1, key, mockMetricsManager);
+    EXPECT_EQ(0, broadcastCount);
+}
+
+#else
+GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
\ No newline at end of file
diff --git a/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp b/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp
index 65c2a05..f385763 100644
--- a/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp
+++ b/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp
@@ -30,6 +30,8 @@
 namespace os {
 namespace statsd {
 
+const ConfigKey kConfigKey(0, "test");
+
 void AddValueToBucket(const std::vector<std::pair<string, long>>& key_value_pair_list,
                       std::shared_ptr<DimToValMap> bucket) {
     for (auto itr = key_value_pair_list.begin(); itr != key_value_pair_list.end(); itr++) {
@@ -51,7 +53,7 @@
     alert.set_refractory_period_secs(2 * bucketSizeNs / NS_PER_SEC);
     alert.set_trigger_if_sum_gt(2);
 
-    AnomalyTracker anomalyTracker(alert);
+    AnomalyTracker anomalyTracker(alert, kConfigKey);
 
     std::shared_ptr<DimToValMap> bucket0 = MockBucket({{"a", 1}, {"b", 2}, {"c", 1}});
     int64_t eventTimestamp0 = 10;
@@ -168,7 +170,7 @@
     alert.set_refractory_period_secs(2 * bucketSizeNs / NS_PER_SEC);
     alert.set_trigger_if_sum_gt(2);
 
-    AnomalyTracker anomalyTracker(alert);
+    AnomalyTracker anomalyTracker(alert, kConfigKey);
 
     std::shared_ptr<DimToValMap> bucket9 = MockBucket({{"a", 1}, {"b", 2}, {"c", 1}});
     std::shared_ptr<DimToValMap> bucket16 = MockBucket({{"b", 4}});
diff --git a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
index a8193dd..9fed4f8 100644
--- a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
+++ b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
@@ -118,6 +118,10 @@
     stats.noteMetricDimensionSize(key, "metric1", 201);
     stats.noteMetricDimensionSize(key, "metric1", 202);
 
+    stats.noteAnomalyDeclared(key, "alert1");
+    stats.noteAnomalyDeclared(key, "alert1");
+    stats.noteAnomalyDeclared(key, "alert2");
+
     // broadcast-> 2
     stats.noteBroadcastSent(key);
     stats.noteBroadcastSent(key);
@@ -142,7 +146,6 @@
     EXPECT_EQ(3, configReport.dump_report_time_sec_size());
 
     EXPECT_EQ(2, configReport.matcher_stats_size());
-
     // matcher1 is the first in the list
     if (!configReport.matcher_stats(0).name().compare("matcher1")) {
         EXPECT_EQ(2, configReport.matcher_stats(0).matched_times());
@@ -157,6 +160,13 @@
         EXPECT_EQ("matcher1", configReport.matcher_stats(1).name());
     }
 
+    EXPECT_EQ(2, configReport.alert_stats_size());
+    bool alert1first = !configReport.alert_stats(0).name().compare("alert1");
+    EXPECT_EQ("alert1", configReport.alert_stats(alert1first ? 0 : 1).name());
+    EXPECT_EQ(2, configReport.alert_stats(alert1first ? 0 : 1).declared_times());
+    EXPECT_EQ("alert2", configReport.alert_stats(alert1first ? 1 : 0).name());
+    EXPECT_EQ(1, configReport.alert_stats(alert1first ? 1 : 0).declared_times());
+
     EXPECT_EQ(1, configReport.condition_stats_size());
     EXPECT_EQ("condition1", configReport.condition_stats(0).name());
     EXPECT_EQ(250, configReport.condition_stats(0).max_tuple_counts());
@@ -169,6 +179,7 @@
     stats.noteMatcherMatched(key, "matcher99");
     stats.noteConditionDimensionSize(key, "condition99", 300);
     stats.noteMetricDimensionSize(key, "metric99", 270);
+    stats.noteAnomalyDeclared(key, "alert99");
 
     // now the config stats should only contain the stats about the new event.
     stats.dumpStats(&output, false);
@@ -187,6 +198,10 @@
     EXPECT_EQ(1, configReport2.metric_stats_size());
     EXPECT_EQ("metric99", configReport2.metric_stats(0).name());
     EXPECT_EQ(270, configReport2.metric_stats(0).max_tuple_counts());
+
+    EXPECT_EQ(1, configReport2.alert_stats_size());
+    EXPECT_EQ("alert99", configReport2.alert_stats(0).name());
+    EXPECT_EQ(1, configReport2.alert_stats(0).declared_times());
 }
 
 TEST(StatsdStatsTest, TestAtomLog) {
@@ -224,6 +239,21 @@
     EXPECT_TRUE(sensorAtomGood);
 }
 
+
+TEST(StatsdStatsTest, TestAnomalyMonitor) {
+    StatsdStats stats;
+    stats.noteRegisteredAnomalyAlarmChanged();
+    stats.noteRegisteredAnomalyAlarmChanged();
+
+    vector<uint8_t> output;
+    stats.dumpStats(&output, false);
+    StatsdStatsReport report;
+    bool good = report.ParseFromArray(&output[0], output.size());
+    EXPECT_TRUE(good);
+
+    EXPECT_EQ(2, report.anomaly_alarm_stats().alarms_registered());
+}
+
 TEST(StatsdStatsTest, TestTimestampThreshold) {
     StatsdStats stats;
     vector<int32_t> timestamps;
diff --git a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
index 9b94099..d973ba1 100644
--- a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
@@ -196,7 +196,7 @@
     int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
     int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
 
-    sp<AnomalyTracker> anomalyTracker = new AnomalyTracker(alert);
+    sp<AnomalyTracker> anomalyTracker = new AnomalyTracker(alert, kConfigKey);
 
     CountMetric metric;
     metric.set_name("1");
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index ed13db2..59475d2 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -33,6 +33,8 @@
 namespace os {
 namespace statsd {
 
+const ConfigKey kConfigKey(0, "test");
+
 TEST(GaugeMetricProducerTest, TestWithCondition) {
     int64_t bucketStartTimeNs = 10000000000;
     int64_t bucketSizeNs = 60 * 1000 * 1000 * 1000LL;
@@ -148,7 +150,7 @@
     alert.set_metric_name("1");
     alert.set_trigger_if_sum_gt(25);
     alert.set_number_of_buckets(2);
-    sp<AnomalyTracker> anomalyTracker = new AnomalyTracker(alert);
+    sp<AnomalyTracker> anomalyTracker = new AnomalyTracker(alert, kConfigKey);
     gaugeProducer.addAnomalyTracker(anomalyTracker);
 
     std::shared_ptr<LogEvent> event1 = std::make_shared<LogEvent>(1, bucketStartTimeNs + 1);
diff --git a/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp b/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp
index 1adcc11..4e5e0d6 100644
--- a/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp
+++ b/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp
@@ -208,7 +208,7 @@
     uint64_t eventStartTimeNs = bucketStartTimeNs + NS_PER_SEC + 1;
     uint64_t bucketSizeNs = 30 * NS_PER_SEC;
 
-    sp<AnomalyTracker> anomalyTracker = new AnomalyTracker(alert);
+    sp<AnomalyTracker> anomalyTracker = new AnomalyTracker(alert, kConfigKey);
     MaxDurationTracker tracker(kConfigKey, "metric", eventKey, wizard, -1, true, bucketStartTimeNs,
                                bucketSizeNs, {anomalyTracker});
 
diff --git a/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp b/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
index fa7b9a7..99d3e05 100644
--- a/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
+++ b/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
@@ -269,7 +269,7 @@
     uint64_t eventStartTimeNs = bucketStartTimeNs + NS_PER_SEC + 1;
     uint64_t bucketSizeNs = 30 * NS_PER_SEC;
 
-    sp<AnomalyTracker> anomalyTracker = new AnomalyTracker(alert);
+    sp<AnomalyTracker> anomalyTracker = new AnomalyTracker(alert, kConfigKey);
     OringDurationTracker tracker(kConfigKey, "metric", eventKey, wizard, 1, true, bucketStartTimeNs,
                                  bucketSizeNs, {anomalyTracker});
 
@@ -331,7 +331,7 @@
     uint64_t eventStartTimeNs = bucketStartTimeNs + NS_PER_SEC + 1;
     uint64_t bucketSizeNs = 30 * NS_PER_SEC;
 
-    sp<AnomalyTracker> anomalyTracker = new AnomalyTracker(alert);
+    sp<AnomalyTracker> anomalyTracker = new AnomalyTracker(alert, kConfigKey);
     OringDurationTracker tracker(kConfigKey, "metric", eventKey, wizard, 1, true /*nesting*/,
                                  bucketStartTimeNs, bucketSizeNs, {anomalyTracker});
 
diff --git a/core/java/android/app/VrManager.java b/core/java/android/app/VrManager.java
index 392387a..61b90e1 100644
--- a/core/java/android/app/VrManager.java
+++ b/core/java/android/app/VrManager.java
@@ -4,6 +4,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.TestApi;
 import android.content.ComponentName;
 import android.content.Context;
 import android.os.Handler;
@@ -214,4 +215,22 @@
             e.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Start VR Input method for the packageName in {@link ComponentName}.
+     * This method notifies InputMethodManagerService to use VR IME instead of
+     * regular phone IME.
+     * @param componentName ComponentName of a VR InputMethod that should be set as selected
+     * input by InputMethodManagerService.
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS)
+    public void setVrInputMethod(ComponentName componentName) {
+        try {
+            mService.setVrInputMethod(componentName);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 1241f23..838d315 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -678,33 +678,6 @@
     }
 
     /**
-     * Get battery usage hint for Bluetooth Headset service.
-     * This is a monotonically increasing integer. Wraps to 0 at
-     * Integer.MAX_INT, and at boot.
-     * Current implementation returns the number of AT commands handled since
-     * boot. This is a good indicator for spammy headset/handsfree units that
-     * can keep the device awake by polling for cellular status updates. As a
-     * rule of thumb, each AT command prevents the CPU from sleeping for 500 ms
-     *
-     * @param device the bluetooth headset.
-     * @return monotonically increasing battery usage hint, or a negative error code on error
-     * @hide
-     */
-    public int getBatteryUsageHint(BluetoothDevice device) {
-        if (VDBG) log("getBatteryUsageHint()");
-        final IBluetoothHeadset service = mService;
-        if (service != null && isEnabled() && isValidDevice(device)) {
-            try {
-                return service.getBatteryUsageHint(device);
-            } catch (RemoteException e) {
-                Log.e(TAG, Log.getStackTraceString(new Throwable()));
-            }
-        }
-        if (service == null) Log.w(TAG, "Proxy not attached to service");
-        return -1;
-    }
-
-    /**
      * Indicates if current platform supports voice dialing over bluetooth SCO.
      *
      * @return true if voice dialing over bluetooth is supported, false otherwise.
@@ -716,49 +689,6 @@
     }
 
     /**
-     * Accept the incoming connection.
-     * Note: This is an internal function and shouldn't be exposed
-     *
-     * @hide
-     */
-    public boolean acceptIncomingConnect(BluetoothDevice device) {
-        if (DBG) log("acceptIncomingConnect");
-        final IBluetoothHeadset service = mService;
-        if (service != null && isEnabled()) {
-            try {
-                return service.acceptIncomingConnect(device);
-            } catch (RemoteException e) {
-                Log.e(TAG, e.toString());
-            }
-        } else {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
-        }
-        return false;
-    }
-
-    /**
-     * Reject the incoming connection.
-     *
-     * @hide
-     */
-    public boolean rejectIncomingConnect(BluetoothDevice device) {
-        if (DBG) log("rejectIncomingConnect");
-        final IBluetoothHeadset service = mService;
-        if (service != null) {
-            try {
-                return service.rejectIncomingConnect(device);
-            } catch (RemoteException e) {
-                Log.e(TAG, e.toString());
-            }
-        } else {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
-        }
-        return false;
-    }
-
-    /**
      * Get the current audio state of the Headset.
      * Note: This is an internal function and shouldn't be exposed
      *
@@ -1053,50 +983,6 @@
     }
 
     /**
-     * enable WBS codec setting.
-     *
-     * @return true if successful false if there was some error such as there is no connected
-     * headset
-     * @hide
-     */
-    public boolean enableWBS() {
-        final IBluetoothHeadset service = mService;
-        if (service != null && isEnabled()) {
-            try {
-                return service.enableWBS();
-            } catch (RemoteException e) {
-                Log.e(TAG, e.toString());
-            }
-        } else {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
-        }
-        return false;
-    }
-
-    /**
-     * disable WBS codec settting. It set NBS codec.
-     *
-     * @return true if successful false if there was some error such as there is no connected
-     * headset
-     * @hide
-     */
-    public boolean disableWBS() {
-        final IBluetoothHeadset service = mService;
-        if (service != null && isEnabled()) {
-            try {
-                return service.disableWBS();
-            } catch (RemoteException e) {
-                Log.e(TAG, e.toString());
-            }
-        } else {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
-        }
-        return false;
-    }
-
-    /**
      * check if in-band ringing is supported for this platform.
      *
      * @return true if in-band ringing is supported false if in-band ringing is not supported
@@ -1107,30 +993,6 @@
                 com.android.internal.R.bool.config_bluetooth_hfp_inband_ringing_support);
     }
 
-    /**
-     * Send Headset the BIND response from AG to report change in the status of the
-     * HF indicators to the headset
-     *
-     * @param indId Assigned Number of the indicator (defined by SIG)
-     * @param indStatus possible values- false-Indicator is disabled, no value changes shall be
-     * sent for this indicator true-Indicator is enabled, value changes may be sent for this
-     * indicator
-     * @hide
-     */
-    public void bindResponse(int indId, boolean indStatus) {
-        final IBluetoothHeadset service = mService;
-        if (service != null && isEnabled()) {
-            try {
-                service.bindResponse(indId, indStatus);
-            } catch (RemoteException e) {
-                Log.e(TAG, e.toString());
-            }
-        } else {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
-        }
-    }
-
     private final IBluetoothProfileServiceConnection mConnection =
             new IBluetoothProfileServiceConnection.Stub() {
         @Override
diff --git a/core/java/android/bluetooth/BluetoothHidDevice.java b/core/java/android/bluetooth/BluetoothHidDevice.java
index bfee2797..4a00486 100644
--- a/core/java/android/bluetooth/BluetoothHidDevice.java
+++ b/core/java/android/bluetooth/BluetoothHidDevice.java
@@ -31,36 +31,33 @@
 import java.util.List;
 
 /**
- * Provides the public APIs to control the Bluetooth HID Device
- * profile.
+ * Provides the public APIs to control the Bluetooth HID Device profile.
  *
- * BluetoothHidDevice is a proxy object for controlling the Bluetooth HID
- * Device Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
- * the BluetoothHidDevice proxy object.
+ * <p>BluetoothHidDevice is a proxy object for controlling the Bluetooth HID Device Service via IPC.
+ * Use {@link BluetoothAdapter#getProfileProxy} to get the BluetoothHidDevice proxy object.
  *
- * {@hide}
+ * <p>{@hide}
  */
 public final class BluetoothHidDevice implements BluetoothProfile {
 
     private static final String TAG = BluetoothHidDevice.class.getSimpleName();
 
     /**
-     * Intent used to broadcast the change in connection state of the Input
-     * Host profile.
+     * Intent used to broadcast the change in connection state of the Input Host profile.
      *
      * <p>This intent will have 3 extras:
+     *
      * <ul>
-     * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
-     * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
-     * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
+     *   <li>{@link #EXTRA_STATE} - The current state of the profile.
+     *   <li>{@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.
+     *   <li>{@link BluetoothDevice#EXTRA_DEVICE} - The remote device.
      * </ul>
      *
-     * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
-     * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
-     * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
+     * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of {@link
+     * #STATE_DISCONNECTED}, {@link #STATE_CONNECTING}, {@link #STATE_CONNECTED}, {@link
+     * #STATE_DISCONNECTING}.
      *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
-     * receive.
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to receive.
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_CONNECTION_STATE_CHANGED =
@@ -69,9 +66,8 @@
     /**
      * Constants representing device subclass.
      *
-     * @see #registerApp
-     * (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
-     * BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceCallback)
+     * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
+     *     BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceCallback)
      */
     public static final byte SUBCLASS1_NONE = (byte) 0x00;
     public static final byte SUBCLASS1_KEYBOARD = (byte) 0x40;
@@ -110,8 +106,8 @@
     public static final byte ERROR_RSP_UNKNOWN = (byte) 14;
 
     /**
-     * Constants representing protocol mode used set by host. Default is always
-     * {@link #PROTOCOL_REPORT_MODE} unless notified otherwise.
+     * Constants representing protocol mode used set by host. Default is always {@link
+     * #PROTOCOL_REPORT_MODE} unless notified otherwise.
      *
      * @see BluetoothHidDeviceCallback#onSetProtocol(BluetoothDevice, byte)
      */
@@ -126,8 +122,8 @@
 
     private BluetoothAdapter mAdapter;
 
-    private static class BluetoothHidDeviceCallbackWrapper extends
-            IBluetoothHidDeviceCallback.Stub {
+    private static class BluetoothHidDeviceCallbackWrapper
+            extends IBluetoothHidDeviceCallback.Stub {
 
         private BluetoothHidDeviceCallback mCallback;
 
@@ -184,13 +180,11 @@
                                     doBind();
                                 }
                             } catch (IllegalStateException e) {
-                                Log.e(TAG,
-                                        "onBluetoothStateChange: could not bind to HID Dev "
-                                                + "service: ", e);
+                                Log.e(TAG, "onBluetoothStateChange: could not bind to HID Dev "
+                                        + "service: ", e);
                             } catch (SecurityException e) {
-                                Log.e(TAG,
-                                        "onBluetoothStateChange: could not bind to HID Dev "
-                                                + "service: ", e);
+                                Log.e(TAG, "onBluetoothStateChange: could not bind to HID Dev "
+                                        + "service: ", e);
                             }
                         } else {
                             Log.d(TAG, "Unbinding service...");
@@ -200,23 +194,25 @@
                 }
             };
 
-    private final ServiceConnection mConnection = new ServiceConnection() {
-        public void onServiceConnected(ComponentName className, IBinder service) {
-            Log.d(TAG, "onServiceConnected()");
-            mService = IBluetoothHidDevice.Stub.asInterface(service);
-            if (mServiceListener != null) {
-                mServiceListener.onServiceConnected(BluetoothProfile.HID_DEVICE,
-                        BluetoothHidDevice.this);
-            }
-        }
-        public void onServiceDisconnected(ComponentName className) {
-            Log.d(TAG, "onServiceDisconnected()");
-            mService = null;
-            if (mServiceListener != null) {
-                mServiceListener.onServiceDisconnected(BluetoothProfile.HID_DEVICE);
-            }
-        }
-    };
+    private final ServiceConnection mConnection =
+            new ServiceConnection() {
+                public void onServiceConnected(ComponentName className, IBinder service) {
+                    Log.d(TAG, "onServiceConnected()");
+                    mService = IBluetoothHidDevice.Stub.asInterface(service);
+                    if (mServiceListener != null) {
+                        mServiceListener.onServiceConnected(
+                                BluetoothProfile.HID_DEVICE, BluetoothHidDevice.this);
+                    }
+                }
+
+                public void onServiceDisconnected(ComponentName className) {
+                    Log.d(TAG, "onServiceDisconnected()");
+                    mService = null;
+                    if (mServiceListener != null) {
+                        mServiceListener.onServiceDisconnected(BluetoothProfile.HID_DEVICE);
+                    }
+                }
+            };
 
     BluetoothHidDevice(Context context, ServiceListener listener) {
         Log.v(TAG, "BluetoothHidDevice");
@@ -280,9 +276,7 @@
         mServiceListener = null;
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     @Override
     public List<BluetoothDevice> getConnectedDevices() {
         Log.v(TAG, "getConnectedDevices()");
@@ -301,9 +295,7 @@
         return new ArrayList<BluetoothDevice>();
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     @Override
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
         Log.v(TAG, "getDevicesMatchingConnectionStates(): states=" + Arrays.toString(states));
@@ -322,9 +314,7 @@
         return new ArrayList<BluetoothDevice>();
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     @Override
     public int getConnectionState(BluetoothDevice device) {
         Log.v(TAG, "getConnectionState(): device=" + device);
@@ -344,33 +334,31 @@
     }
 
     /**
-     * Registers application to be used for HID device. Connections to HID
-     * Device are only possible when application is registered. Only one
-     * application can be registered at time. When no longer used, application
-     * should be unregistered using
-     * {@link #unregisterApp()}.
-     * The registration status should be tracked by the application by handling callback from
-     * BluetoothHidDeviceCallback#onAppStatusChanged. The app registration status is not related
-     * to the return value of this method.
+     * Registers application to be used for HID device. Connections to HID Device are only possible
+     * when application is registered. Only one application can be registered at one time. When an
+     * application is registered, the HID Host service will be disabled until it is unregistered.
+     * When no longer used, application should be unregistered using {@link #unregisterApp()}. The
+     * registration status should be tracked by the application by handling callback from
+     * BluetoothHidDeviceCallback#onAppStatusChanged. The app registration status is not related to
+     * the return value of this method.
      *
-     * @param sdp {@link BluetoothHidDeviceAppSdpSettings} object of HID Device SDP record.
-     * The HID Device SDP record is required.
-     * @param inQos {@link BluetoothHidDeviceAppQosSettings} object of Incoming QoS Settings.
-     * The Incoming QoS Settings is not required. Use null or default
-     * BluetoothHidDeviceAppQosSettings.Builder for default values.
-     * @param outQos {@link BluetoothHidDeviceAppQosSettings} object of Outgoing QoS Settings.
-     * The Outgoing QoS Settings is not required. Use null or default
-     * BluetoothHidDeviceAppQosSettings.Builder for default values.
+     * @param sdp {@link BluetoothHidDeviceAppSdpSettings} object of HID Device SDP record. The HID
+     *     Device SDP record is required.
+     * @param inQos {@link BluetoothHidDeviceAppQosSettings} object of Incoming QoS Settings. The
+     *     Incoming QoS Settings is not required. Use null or default
+     *     BluetoothHidDeviceAppQosSettings.Builder for default values.
+     * @param outQos {@link BluetoothHidDeviceAppQosSettings} object of Outgoing QoS Settings. The
+     *     Outgoing QoS Settings is not required. Use null or default
+     *     BluetoothHidDeviceAppQosSettings.Builder for default values.
      * @param callback {@link BluetoothHidDeviceCallback} object to which callback messages will be
-     * sent.
-     * The BluetoothHidDeviceCallback object is required.
+     *     sent. The BluetoothHidDeviceCallback object is required.
      * @return true if the command is successfully sent; otherwise false.
      */
     public boolean registerApp(BluetoothHidDeviceAppSdpSettings sdp,
             BluetoothHidDeviceAppQosSettings inQos, BluetoothHidDeviceAppQosSettings outQos,
             BluetoothHidDeviceCallback callback) {
         Log.v(TAG, "registerApp(): sdp=" + sdp + " inQos=" + inQos + " outQos=" + outQos
-                + " callback=" + callback);
+                        + " callback=" + callback);
 
         boolean result = false;
 
@@ -395,14 +383,13 @@
     }
 
     /**
-     * Unregisters application. Active connection will be disconnected and no
-     * new connections will be allowed until registered again using
-     * {@link #registerApp
+     * Unregisters application. Active connection will be disconnected and no new connections will
+     * be allowed until registered again using {@link #registerApp
      * (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
-     * BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceCallback)}
-     * The registration status should be tracked by the application by handling callback from
-     * BluetoothHidDeviceCallback#onAppStatusChanged. The app registration status is not related
-     * to the return value of this method.
+     * BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceCallback)} The registration status should
+     * be tracked by the application by handling callback from
+     * BluetoothHidDeviceCallback#onAppStatusChanged. The app registration status is not related to
+     * the return value of this method.
      *
      * @return true if the command is successfully sent; otherwise false.
      */
@@ -429,7 +416,7 @@
      * Sends report to remote host using interrupt channel.
      *
      * @param id Report Id, as defined in descriptor. Can be 0 in case Report Id are not defined in
-     * descriptor.
+     *     descriptor.
      * @param data Report data, not including Report Id.
      * @return true if the command is successfully sent; otherwise false.
      */
@@ -451,8 +438,8 @@
     }
 
     /**
-     * Sends report to remote host as reply for GET_REPORT request from
-     * {@link BluetoothHidDeviceCallback#onGetReport(BluetoothDevice, byte, byte, int)}.
+     * Sends report to remote host as reply for GET_REPORT request from {@link
+     * BluetoothHidDeviceCallback#onGetReport(BluetoothDevice, byte, byte, int)}.
      *
      * @param type Report Type, as in request.
      * @param id Report Id, as in request.
@@ -479,8 +466,8 @@
     }
 
     /**
-     * Sends error handshake message as reply for invalid SET_REPORT request
-     * from {@link BluetoothHidDeviceCallback#onSetReport(BluetoothDevice, byte, byte, byte[])}.
+     * Sends error handshake message as reply for invalid SET_REPORT request from {@link
+     * BluetoothHidDeviceCallback#onSetReport(BluetoothDevice, byte, byte, byte[])}.
      *
      * @param error Error to be sent for SET_REPORT via HANDSHAKE.
      * @return true if the command is successfully sent; otherwise false.
@@ -508,6 +495,7 @@
      * Sends Virtual Cable Unplug to currently connected host.
      *
      * @return
+     * {@hide}
      */
     public boolean unplug(BluetoothDevice device) {
         Log.v(TAG, "unplug(): device=" + device);
@@ -529,11 +517,11 @@
     }
 
     /**
-     * Initiates connection to host which is currently paired with this device.
-     * If the application is not registered, #connect(BluetoothDevice) will fail.
-     * The connection state should be tracked by the application by handling callback from
-     * BluetoothHidDeviceCallback#onConnectionStateChanged. The connection state is not related
-     * to the return value of this method.
+     * Initiates connection to host which is currently paired with this device. If the application
+     * is not registered, #connect(BluetoothDevice) will fail. The connection state should be
+     * tracked by the application by handling callback from
+     * BluetoothHidDeviceCallback#onConnectionStateChanged. The connection state is not related to
+     * the return value of this method.
      *
      * @return true if the command is successfully sent; otherwise false.
      */
@@ -557,10 +545,9 @@
     }
 
     /**
-     * Disconnects from currently connected host.
-     * The connection state should be tracked by the application by handling callback from
-     * BluetoothHidDeviceCallback#onConnectionStateChanged. The connection state is not related
-     * to the return value of this method.
+     * Disconnects from currently connected host. The connection state should be tracked by the
+     * application by handling callback from BluetoothHidDeviceCallback#onConnectionStateChanged.
+     * The connection state is not related to the return value of this method.
      *
      * @return true if the command is successfully sent; otherwise false.
      */
diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java b/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java
index 881ae98..4609d52 100644
--- a/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java
+++ b/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java
@@ -20,15 +20,14 @@
 import android.os.Parcelable;
 
 /**
- * Represents the Quality of Service (QoS) settings for a Bluetooth HID Device
- * application.
+ * Represents the Quality of Service (QoS) settings for a Bluetooth HID Device application.
  *
- * The BluetoothHidDevice framework will update the L2CAP QoS settings for the
- * app during registration.
+ * <p>The BluetoothHidDevice framework will update the L2CAP QoS settings for the app during
+ * registration.
  *
- * {@see BluetoothHidDevice}
+ * <p>{@see BluetoothHidDevice}
  *
- * {@hide}
+ * <p>{@hide}
  */
 public final class BluetoothHidDeviceAppQosSettings implements Parcelable {
 
@@ -46,13 +45,12 @@
     public static final int MAX = (int) 0xffffffff;
 
     /**
-     * Create a BluetoothHidDeviceAppQosSettings object for the Bluetooth L2CAP channel.
-     * The QoS Settings is optional.
-     * Recommended to use BluetoothHidDeviceAppQosSettings.Builder.
-     * {@see <a href="https://www.bluetooth.com/specifications/profiles-overview">
-     *     https://www.bluetooth.com/specifications/profiles-overview
-     *     </a>
-     *     Bluetooth HID Specfication v1.1.1 Section 5.2 and Appendix D }
+     * Create a BluetoothHidDeviceAppQosSettings object for the Bluetooth L2CAP channel. The QoS
+     * Settings is optional. Recommended to use BluetoothHidDeviceAppQosSettings.Builder. {@see <a
+     * href="https://www.bluetooth.com/specifications/profiles-overview">
+     * https://www.bluetooth.com/specifications/profiles-overview </a> Bluetooth HID Specfication
+     * v1.1.1 Section 5.2 and Appendix D }
+     *
      * @param serviceType L2CAP service type
      * @param tokenRate L2CAP token rate
      * @param tokenBucketSize L2CAP token bucket size
@@ -123,13 +121,11 @@
     /** @return an int array representation of this instance */
     public int[] toArray() {
         return new int[] {
-                serviceType, tokenRate, tokenBucketSize, peakBandwidth, latency, delayVariation
+            serviceType, tokenRate, tokenBucketSize, peakBandwidth, latency, delayVariation
         };
     }
 
-    /**
-     * A helper to build the BluetoothHidDeviceAppQosSettings object.
-     */
+    /** A helper to build the BluetoothHidDeviceAppQosSettings object. */
     public static class Builder {
         // Optional parameters - initialized to default values
         private int mServiceType = SERVICE_BEST_EFFORT;
@@ -141,8 +137,9 @@
 
         /**
          * Set the service type.
+         *
          * @param val service type. Should be one of {SERVICE_NO_TRAFFIC, SERVICE_BEST_EFFORT,
-         * SERVICE_GUARANTEED}, with SERVICE_BEST_EFFORT being the default one.
+         *     SERVICE_GUARANTEED}, with SERVICE_BEST_EFFORT being the default one.
          * @return BluetoothHidDeviceAppQosSettings Builder with specified service type.
          */
         public Builder serviceType(int val) {
@@ -151,6 +148,7 @@
         }
         /**
          * Set the token rate.
+         *
          * @param val token rate
          * @return BluetoothHidDeviceAppQosSettings Builder with specified token rate.
          */
@@ -161,6 +159,7 @@
 
         /**
          * Set the bucket size.
+         *
          * @param val bucket size
          * @return BluetoothHidDeviceAppQosSettings Builder with specified bucket size.
          */
@@ -171,6 +170,7 @@
 
         /**
          * Set the peak bandwidth.
+         *
          * @param val peak bandwidth
          * @return BluetoothHidDeviceAppQosSettings Builder with specified peak bandwidth.
          */
@@ -180,6 +180,7 @@
         }
         /**
          * Set the latency.
+         *
          * @param val latency
          * @return BluetoothHidDeviceAppQosSettings Builder with specified latency.
          */
@@ -190,6 +191,7 @@
 
         /**
          * Set the delay variation.
+         *
          * @param val delay variation
          * @return BluetoothHidDeviceAppQosSettings Builder with specified delay variation.
          */
@@ -200,6 +202,7 @@
 
         /**
          * Build the BluetoothHidDeviceAppQosSettings object.
+         *
          * @return BluetoothHidDeviceAppQosSettings object with current settings.
          */
         public BluetoothHidDeviceAppQosSettings build() {
diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java b/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java
index 4669637..2da64e5 100644
--- a/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java
+++ b/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java
@@ -22,16 +22,14 @@
 import java.util.Arrays;
 
 /**
- * Represents the Service Discovery Protocol (SDP) settings for a Bluetooth
- * HID Device application.
+ * Represents the Service Discovery Protocol (SDP) settings for a Bluetooth HID Device application.
  *
- * The BluetoothHidDevice framework adds the SDP record during app
- * registration, so that the Android device can be discovered as a Bluetooth
- * HID Device.
+ * <p>The BluetoothHidDevice framework adds the SDP record during app registration, so that the
+ * Android device can be discovered as a Bluetooth HID Device.
  *
- * {@see BluetoothHidDevice}
+ * <p>{@see BluetoothHidDevice}
  *
- * {@hide}
+ * <p>{@hide}
  */
 public final class BluetoothHidDeviceAppSdpSettings implements Parcelable {
 
@@ -43,18 +41,19 @@
 
     /**
      * Create a BluetoothHidDeviceAppSdpSettings object for the Bluetooth SDP record.
+     *
      * @param name Name of this Bluetooth HID device. Maximum length is 50 bytes.
      * @param description Description for this Bluetooth HID device. Maximum length is 50 bytes.
      * @param provider Provider of this Bluetooth HID device. Maximum length is 50 bytes.
-     * @param subclass Subclass of this Bluetooth HID device.
-     * See <a href="www.usb.org/developers/hidpage/HID1_11.pdf">
+     * @param subclass Subclass of this Bluetooth HID device. See <a
+     *     href="www.usb.org/developers/hidpage/HID1_11.pdf">
      *     www.usb.org/developers/hidpage/HID1_11.pdf Section 4.2</a>
-     * @param descriptors Descriptors of this Bluetooth HID device.
-     * See <a href="www.usb.org/developers/hidpage/HID1_11.pdf">
+     * @param descriptors Descriptors of this Bluetooth HID device. See <a
+     *     href="www.usb.org/developers/hidpage/HID1_11.pdf">
      *     www.usb.org/developers/hidpage/HID1_11.pdf Chapter 6</a> Maximum length is 2048 bytes.
      */
-    public BluetoothHidDeviceAppSdpSettings(String name, String description, String provider,
-            byte subclass, byte[] descriptors) {
+    public BluetoothHidDeviceAppSdpSettings(
+            String name, String description, String provider, byte subclass, byte[] descriptors) {
         this.name = name;
         this.description = description;
         this.provider = provider;
diff --git a/core/java/android/bluetooth/BluetoothHidDeviceCallback.java b/core/java/android/bluetooth/BluetoothHidDeviceCallback.java
index dc6f9fa..6ed1965 100644
--- a/core/java/android/bluetooth/BluetoothHidDeviceCallback.java
+++ b/core/java/android/bluetooth/BluetoothHidDeviceCallback.java
@@ -19,46 +19,43 @@
 import android.util.Log;
 
 /**
- * The template class that applications use to call callback functions on
- * events from the HID host. Callback functions are wrapped in this class and
- * registered to the Android system during app registration.
+ * The template class that applications use to call callback functions on events from the HID host.
+ * Callback functions are wrapped in this class and registered to the Android system during app
+ * registration.
  *
- * {@see BluetoothHidDevice}
+ * <p>{@see BluetoothHidDevice}
  *
- * {@hide}
+ * <p>{@hide}
  */
 public abstract class BluetoothHidDeviceCallback {
 
     private static final String TAG = "BluetoothHidDevCallback";
 
     /**
-     * Callback called when application registration state changes. Usually it's
-     * called due to either
-     * {@link BluetoothHidDevice#registerApp
-     * (String, String, String, byte, byte[], BluetoothHidDeviceCallback)}
-     * or
-     * {@link BluetoothHidDevice#unregisterApp()}
-     * , but can be also unsolicited in case e.g. Bluetooth was turned off in
-     * which case application is unregistered automatically.
+     * Callback called when application registration state changes. Usually it's called due to
+     * either {@link BluetoothHidDevice#registerApp (String, String, String, byte, byte[],
+     * BluetoothHidDeviceCallback)} or {@link BluetoothHidDevice#unregisterApp()} , but can be also
+     * unsolicited in case e.g. Bluetooth was turned off in which case application is unregistered
+     * automatically.
      *
      * @param pluggedDevice {@link BluetoothDevice} object which represents host that currently has
-     * Virtual Cable established with device. Only valid when application is registered, can be
-     * <code>null</code>.
+     *     Virtual Cable established with device. Only valid when application is registered, can be
+     *     <code>null</code>.
      * @param registered <code>true</code> if application is registered, <code>false</code>
-     * otherwise.
+     *     otherwise.
      */
     public void onAppStatusChanged(BluetoothDevice pluggedDevice, boolean registered) {
-        Log.d(TAG, "onAppStatusChanged: pluggedDevice=" + pluggedDevice + " registered="
-                + registered);
+        Log.d(TAG,
+                "onAppStatusChanged: pluggedDevice=" + pluggedDevice + " registered=" + registered);
     }
 
     /**
-     * Callback called when connection state with remote host was changed.
-     * Application can assume than Virtual Cable is established when called with
-     * {@link BluetoothProfile#STATE_CONNECTED} <code>state</code>.
+     * Callback called when connection state with remote host was changed. Application can assume
+     * than Virtual Cable is established when called with {@link BluetoothProfile#STATE_CONNECTED}
+     * <code>state</code>.
      *
      * @param device {@link BluetoothDevice} object representing host device which connection state
-     * was changed.
+     *     was changed.
      * @param state Connection state as defined in {@link BluetoothProfile}.
      */
     public void onConnectionStateChanged(BluetoothDevice device, int state) {
@@ -66,14 +63,14 @@
     }
 
     /**
-     * Callback called when GET_REPORT is received from remote host. Should be
-     * replied by application using
-     * {@link BluetoothHidDevice#replyReport(BluetoothDevice, byte, byte, byte[])}.
+     * Callback called when GET_REPORT is received from remote host. Should be replied by
+     * application using {@link BluetoothHidDevice#replyReport(BluetoothDevice, byte, byte,
+     * byte[])}.
      *
      * @param type Requested Report Type.
      * @param id Requested Report Id, can be 0 if no Report Id are defined in descriptor.
      * @param bufferSize Requested buffer size, application shall respond with at least given number
-     * of bytes.
+     *     of bytes.
      */
     public void onGetReport(BluetoothDevice device, byte type, byte id, int bufferSize) {
         Log.d(TAG, "onGetReport: device=" + device + " type=" + type + " id=" + id + " bufferSize="
@@ -81,9 +78,9 @@
     }
 
     /**
-     * Callback called when SET_REPORT is received from remote host. In case
-     * received data are invalid, application shall respond with
-     * {@link BluetoothHidDevice#reportError(BluetoothDevice, byte)}.
+     * Callback called when SET_REPORT is received from remote host. In case received data are
+     * invalid, application shall respond with {@link
+     * BluetoothHidDevice#reportError(BluetoothDevice, byte)}.
      *
      * @param type Report Type.
      * @param id Report Id.
@@ -94,10 +91,9 @@
     }
 
     /**
-     * Callback called when SET_PROTOCOL is received from remote host.
-     * Application shall use this information to send only reports valid for
-     * given protocol mode. By default,
-     * {@link BluetoothHidDevice#PROTOCOL_REPORT_MODE} shall be assumed.
+     * Callback called when SET_PROTOCOL is received from remote host. Application shall use this
+     * information to send only reports valid for given protocol mode. By default, {@link
+     * BluetoothHidDevice#PROTOCOL_REPORT_MODE} shall be assumed.
      *
      * @param protocol Protocol Mode.
      */
@@ -106,9 +102,8 @@
     }
 
     /**
-     * Callback called when report data is received over interrupt channel.
-     * Report Type is assumed to be
-     * {@link BluetoothHidDevice#REPORT_TYPE_OUTPUT}.
+     * Callback called when report data is received over interrupt channel. Report Type is assumed
+     * to be {@link BluetoothHidDevice#REPORT_TYPE_OUTPUT}.
      *
      * @param reportId Report Id.
      * @param data Report data.
@@ -118,10 +113,8 @@
     }
 
     /**
-     * Callback called when Virtual Cable is removed. This can be either due to
-     * {@link BluetoothHidDevice#unplug(BluetoothDevice)} or request from remote
-     * side. After this callback is received connection will be disconnected
-     * automatically.
+     * Callback called when Virtual Cable is removed. After this callback is
+     * received connection will be disconnected automatically.
      */
     public void onVirtualCableUnplug(BluetoothDevice device) {
         Log.d(TAG, "onVirtualCableUnplug: device=" + device);
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 9e54e23..d09ba0b 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -265,6 +265,14 @@
 
         /**
          * Include pinned shortcuts in the result.
+         *
+         * <p>If you are the selected assistant app, and wishes to fetch all shortcuts that the
+         * user owns on the launcher (or by other launchers, in case the user has multiple), use
+         * {@link #FLAG_MATCH_PINNED_BY_ANY_LAUNCHER} instead.
+         *
+         * <p>If you're a regular launcher app, there's no way to get shortcuts pinned by other
+         * launchers, and {@link #FLAG_MATCH_PINNED_BY_ANY_LAUNCHER} will be ignored. So use this
+         * flag to get own pinned shortcuts.
          */
         public static final int FLAG_MATCH_PINNED = 1 << 1;
 
@@ -285,8 +293,15 @@
          * Include all pinned shortcuts by any launchers, not just by the caller,
          * in the result.
          *
-         * The caller must be the selected assistant app to use this flag, or have the system
+         * <p>The caller must be the selected assistant app to use this flag, or have the system
          * {@code ACCESS_SHORTCUTS} permission.
+         *
+         * <p>If you are the selected assistant app, and wishes to fetch all shortcuts that the
+         * user owns on the launcher (or by other launchers, in case the user has multiple), use
+         * {@link #FLAG_MATCH_PINNED_BY_ANY_LAUNCHER} instead.
+         *
+         * <p>If you're a regular launcher app (or any app that's not the selected assistant app)
+         * then this flag will be ignored.
          */
         public static final int FLAG_MATCH_PINNED_BY_ANY_LAUNCHER = 1 << 10;
 
diff --git a/core/java/android/content/res/XmlResourceParser.java b/core/java/android/content/res/XmlResourceParser.java
index 5af49d4..6be9b9e 100644
--- a/core/java/android/content/res/XmlResourceParser.java
+++ b/core/java/android/content/res/XmlResourceParser.java
@@ -16,20 +16,19 @@
 
 package android.content.res;
 
-import org.xmlpull.v1.XmlPullParser;
-
 import android.util.AttributeSet;
 
+import org.xmlpull.v1.XmlPullParser;
+
 /**
  * The XML parsing interface returned for an XML resource.  This is a standard
- * XmlPullParser interface, as well as an extended AttributeSet interface and
- * an additional close() method on this interface for the client to indicate
- * when it is done reading the resource.
+ * {@link XmlPullParser} interface but also extends {@link AttributeSet} and
+ * adds an additional {@link #close()} method for the client to indicate when
+ * it is done reading the resource.
  */
 public interface XmlResourceParser extends XmlPullParser, AttributeSet, AutoCloseable {
     /**
-     * Close this interface to the resource.  Calls on the interface are no
-     * longer value after this call.
+     * Close this parser. Calls on the interface are no longer valid after this call.
      */
     public void close();
 }
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index a7a3df7..cb11d0f 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -2729,13 +2729,13 @@
     //
 
     /**
-     * <p>Scene change is not detected within AF regions.</p>
+     * <p>Scene change is not detected within the AF region(s).</p>
      * @see CaptureResult#CONTROL_AF_SCENE_CHANGE
      */
     public static final int CONTROL_AF_SCENE_CHANGE_NOT_DETECTED = 0;
 
     /**
-     * <p>Scene change is detected within AF regions.</p>
+     * <p>Scene change is detected within the AF region(s).</p>
      * @see CaptureResult#CONTROL_AF_SCENE_CHANGE
      */
     public static final int CONTROL_AF_SCENE_CHANGE_DETECTED = 1;
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index b7d7f7d..6d7b06f 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -2185,10 +2185,16 @@
             new Key<Boolean>("android.control.enableZsl", boolean.class);
 
     /**
-     * <p>Whether scene change is detected within AF regions.</p>
-     * <p>When AF detects a scene change within current AF regions, it will be set to DETECTED. Otherwise,
-     * it will be set to NOT_DETECTED. This value will remain NOT_DETECTED if afMode is AF_MODE_OFF or
-     * AF_MODE_EDOF.</p>
+     * <p>Whether a significant scene change is detected within the currently-set AF
+     * region(s).</p>
+     * <p>When the camera focus routine detects a change in the scene it is looking at,
+     * such as a large shift in camera viewpoint, significant motion in the scene, or a
+     * significant illumination change, this value will be set to DETECTED for a single capture
+     * result. Otherwise the value will be NOT_DETECTED. The threshold for detection is similar
+     * to what would trigger a new passive focus scan to begin in CONTINUOUS autofocus modes.</p>
+     * <p>afSceneChange may be DETECTED only if afMode is AF_MODE_CONTINUOUS_VIDEO or
+     * AF_MODE_CONTINUOUS_PICTURE. In other AF modes, afSceneChange must be NOT_DETECTED.</p>
+     * <p>This key will be available if the camera device advertises this key via {@link android.hardware.camera2.CameraCharacteristics#getAvailableCaptureResultKeys }.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #CONTROL_AF_SCENE_CHANGE_NOT_DETECTED NOT_DETECTED}</li>
diff --git a/core/java/android/service/vr/IVrManager.aidl b/core/java/android/service/vr/IVrManager.aidl
index 7285fb4..f7acfc5 100644
--- a/core/java/android/service/vr/IVrManager.aidl
+++ b/core/java/android/service/vr/IVrManager.aidl
@@ -17,6 +17,7 @@
 package android.service.vr;
 
 import android.app.Vr2dDisplayProperties;
+import android.content.ComponentName;
 import android.service.vr.IVrStateCallbacks;
 import android.service.vr.IPersistentVrStateCallbacks;
 
@@ -109,5 +110,13 @@
      * @param standy True if the device is entering standby, false if it's exiting standby.
      */
     void setStandbyEnabled(boolean standby);
+
+    /**
+     * Start VR Input method for the given packageName in {@param componentName}.
+     * This method notifies InputMethodManagerService to use VR IME instead of
+     * regular phone IME.
+     */
+    void setVrInputMethod(in ComponentName componentName);
+
 }
 
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 92d1de8..4d96733 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -697,6 +697,19 @@
         }
     }
 
+    /**
+     * Returns a list of VR InputMethod currently installed.
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS)
+    public List<InputMethodInfo> getVrInputMethodList() {
+        try {
+            return mService.getVrInputMethodList();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     public List<InputMethodInfo> getEnabledInputMethodList() {
         try {
             return mService.getEnabledInputMethodList();
diff --git a/core/java/android/view/inputmethod/InputMethodManagerInternal.java b/core/java/android/view/inputmethod/InputMethodManagerInternal.java
index 77df4e3..e13813e 100644
--- a/core/java/android/view/inputmethod/InputMethodManagerInternal.java
+++ b/core/java/android/view/inputmethod/InputMethodManagerInternal.java
@@ -16,6 +16,8 @@
 
 package android.view.inputmethod;
 
+import android.content.ComponentName;
+
 /**
  * Input method manager local system service interface.
  *
@@ -37,4 +39,9 @@
      * Hides the current input method, if visible.
      */
     void hideCurrentInputMethod();
+
+    /**
+     * Switches to VR InputMethod defined in the packageName of {@param componentName}.
+     */
+    void startVrInputMethodNoCheck(ComponentName componentName);
 }
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index 3e231d0..57efae6 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -836,7 +836,6 @@
         private final Resources mRes;
         private final ContentResolver mResolver;
         private final HashMap<String, InputMethodInfo> mMethodMap;
-        private final ArrayList<InputMethodInfo> mMethodList;
 
         /**
          * On-memory data store to emulate when {@link #mCopyOnWrite} is {@code true}.
@@ -906,7 +905,6 @@
             mRes = res;
             mResolver = resolver;
             mMethodMap = methodMap;
-            mMethodList = methodList;
             switchCurrentUser(userId, copyOnWrite);
         }
 
@@ -1087,7 +1085,7 @@
             final ArrayList<InputMethodInfo> res = new ArrayList<>();
             for (Pair<String, ArrayList<String>> ims: imsList) {
                 InputMethodInfo info = mMethodMap.get(ims.first);
-                if (info != null) {
+                if (info != null && !info.isVrOnly()) {
                     res.add(info);
                 }
             }
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index b979807..ca8624d 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -36,6 +36,7 @@
 interface IInputMethodManager {
     // TODO: Use ParceledListSlice instead
     List<InputMethodInfo> getInputMethodList();
+    List<InputMethodInfo> getVrInputMethodList();
     // TODO: Use ParceledListSlice instead
     List<InputMethodInfo> getEnabledInputMethodList();
     List<InputMethodSubtype> getEnabledInputMethodSubtypeList(in String imiId,
diff --git a/core/java/com/android/internal/widget/NotificationActionListLayout.java b/core/java/com/android/internal/widget/NotificationActionListLayout.java
index 26023b4..e013553 100644
--- a/core/java/com/android/internal/widget/NotificationActionListLayout.java
+++ b/core/java/com/android/internal/widget/NotificationActionListLayout.java
@@ -21,6 +21,7 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.RippleDrawable;
 import android.util.AttributeSet;
 import android.util.Pair;
 import android.view.Gravity;
@@ -203,6 +204,11 @@
     public void onViewAdded(View child) {
         super.onViewAdded(child);
         clearMeasureOrder();
+        // For some reason ripples + notification actions seem to be an unhappy combination
+        // b/69474443 so just turn them off for now.
+        if (child.getBackground() instanceof RippleDrawable) {
+            ((RippleDrawable)child.getBackground()).setForceSoftware(true);
+        }
     }
 
     @Override
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index 0228edb..915fe9d 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -200,6 +200,7 @@
 message WindowContainerProto {
   optional ConfigurationContainerProto configuration_container = 1;
   optional int32 orientation = 2;
+  optional bool visible = 3;
 }
 
 /* represents ConfigurationContainer */
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index ef8f6af..5ccaf5c 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4490,7 +4490,9 @@
     <string name="stk_cc_ussd_to_dial">USSD request is modified to DIAL request.</string>
     <string name="stk_cc_ussd_to_ss">USSD request is modified to SS request.</string>
     <string name="stk_cc_ussd_to_ussd">USSD request is modified to new USSD request.</string>
+    <string name="stk_cc_ussd_to_dial_video">USSD request is modified to Video DIAL request.</string>
     <string name="stk_cc_ss_to_dial">SS request is modified to DIAL request.</string>
+    <string name="stk_cc_ss_to_dial_video">SS request is modified to Video DIAL request.</string>
     <string name="stk_cc_ss_to_ussd">SS request is modified to USSD request.</string>
     <string name="stk_cc_ss_to_ss">SS request is modified to new SS request.</string>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6da24bd..f659360 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1048,9 +1048,11 @@
   <java-symbol type="string" name="stk_cc_ss_to_dial" />
   <java-symbol type="string" name="stk_cc_ss_to_ss" />
   <java-symbol type="string" name="stk_cc_ss_to_ussd" />
+  <java-symbol type="string" name="stk_cc_ss_to_dial_video" />
   <java-symbol type="string" name="stk_cc_ussd_to_dial" />
   <java-symbol type="string" name="stk_cc_ussd_to_ss" />
   <java-symbol type="string" name="stk_cc_ussd_to_ussd" />
+  <java-symbol type="string" name="stk_cc_ussd_to_dial_video" />
   <java-symbol type="string" name="safe_media_volume_warning" />
   <java-symbol type="string" name="media_route_status_scanning" />
   <java-symbol type="string" name="media_route_status_connecting" />
diff --git a/packages/EasterEgg/Android.mk b/packages/EasterEgg/Android.mk
index d4c1e70..a825581 100644
--- a/packages/EasterEgg/Android.mk
+++ b/packages/EasterEgg/Android.mk
@@ -2,17 +2,23 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE_TAGS := optional
+
 LOCAL_STATIC_JAVA_LIBRARIES := \
+    jsr305
+
+LOCAL_STATIC_ANDROID_LIBRARIES := \
     android-support-v4 \
     android-support-v13 \
     android-support-dynamic-animation \
     android-support-v7-recyclerview \
     android-support-v7-preference \
     android-support-v7-appcompat \
-    android-support-v14-preference \
-    jsr305
+    android-support-v14-preference
+
+LOCAL_USE_AAPT2 := true
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 
 LOCAL_PACKAGE_NAME := EasterEgg
 LOCAL_CERTIFICATE := platform
diff --git a/packages/SettingsLib/common.mk b/packages/SettingsLib/common.mk
index 49c5467..9d1c4ca 100644
--- a/packages/SettingsLib/common.mk
+++ b/packages/SettingsLib/common.mk
@@ -21,6 +21,10 @@
 LOCAL_STATIC_ANDROID_LIBRARIES += \
     android-support-v4 \
     apptoolkit-lifecycle-runtime \
+    android-support-v7-recyclerview \
+    android-support-v7-preference \
+    android-support-v7-appcompat \
+    android-support-v14-preference \
     SettingsLib
 else
 LOCAL_RESOURCE_DIR += $(call my-dir)/res
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/DashboardCategory.java b/packages/SettingsLib/src/com/android/settingslib/drawer/DashboardCategory.java
index a966e82..3a03644 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/DashboardCategory.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/DashboardCategory.java
@@ -75,23 +75,27 @@
      * Note: the returned list serves as a read-only list. If tiles needs to be added or removed
      * from the actual tiles list, it should be done through {@link #addTile}, {@link #removeTile}.
      */
-    public List<Tile> getTiles() {
-        return Collections.unmodifiableList(mTiles);
+    public synchronized List<Tile> getTiles() {
+        final List<Tile> result = new ArrayList<>(mTiles.size());
+        for (Tile tile : mTiles) {
+            result.add(tile);
+        }
+        return result;
     }
 
-    public void addTile(Tile tile) {
+    public synchronized void addTile(Tile tile) {
         mTiles.add(tile);
     }
 
-    public void addTile(int n, Tile tile) {
+    public synchronized void addTile(int n, Tile tile) {
         mTiles.add(n, tile);
     }
 
-    public void removeTile(Tile tile) {
+    public synchronized void removeTile(Tile tile) {
         mTiles.remove(tile);
     }
 
-    public void removeTile(int n) {
+    public synchronized void removeTile(int n) {
         mTiles.remove(n);
     }
 
@@ -103,7 +107,7 @@
         return mTiles.get(n);
     }
 
-    public boolean containsComponent(ComponentName component) {
+    public synchronized boolean containsComponent(ComponentName component) {
         for (Tile tile : mTiles) {
             if (TextUtils.equals(tile.intent.getComponent().getClassName(),
                     component.getClassName())) {
@@ -129,7 +133,7 @@
     /**
      * Sort priority value and package name for tiles in this category.
      */
-    public void sortTiles(String skipPackageName) {
+    public synchronized void sortTiles(String skipPackageName) {
         // Sort mTiles based on [priority, package within priority]
         Collections.sort(mTiles, (tile1, tile2) -> {
             final String package1 = tile1.intent.getComponent().getPackageName();
diff --git a/packages/SettingsLib/tests/integ/Android.mk b/packages/SettingsLib/tests/integ/Android.mk
index 7ace048..3c8c8ac 100644
--- a/packages/SettingsLib/tests/integ/Android.mk
+++ b/packages/SettingsLib/tests/integ/Android.mk
@@ -27,6 +27,8 @@
 LOCAL_PACKAGE_NAME := SettingsLibTests
 LOCAL_COMPATIBILITY_SUITE := device-tests
 
+LOCAL_USE_AAPT2 := true
+
 LOCAL_STATIC_JAVA_LIBRARIES := \
     android-support-test \
     espresso-core \
diff --git a/packages/SettingsLib/tests/robotests/Android.mk b/packages/SettingsLib/tests/robotests/Android.mk
index bc1a834..2738027 100644
--- a/packages/SettingsLib/tests/robotests/Android.mk
+++ b/packages/SettingsLib/tests/robotests/Android.mk
@@ -28,6 +28,8 @@
 LOCAL_RESOURCE_DIR := \
     $(LOCAL_PATH)/res
 
+LOCAL_USE_AAPT2 := true
+
 include frameworks/base/packages/SettingsLib/common.mk
 
 include $(BUILD_PACKAGE)
diff --git a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
index 4f6fcb9..70d13e6 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
@@ -59,8 +59,8 @@
     <string name="kg_wrong_password" msgid="4580683060277329277">"Palavra-passe incorreta"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"PIN incorreto"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="4368805541257003755">
-      <item quantity="one">Tente novamente dentro de 1 segundo.</item>
       <item quantity="other">Tente novamente dentro de <xliff:g id="NUMBER">%d</xliff:g> segundos.</item>
+      <item quantity="one">Tente novamente dentro de 1 segundo.</item>
     </plurals>
     <string name="kg_pattern_instructions" msgid="5547646893001491340">"Desenhe o seu padrão"</string>
     <string name="kg_sim_pin_instructions" msgid="6389000973113699187">"Introduza o PIN do cartão SIM."</string>
@@ -97,13 +97,13 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="8364140853305528449">"Desenhou a sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Após mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas sem êxito, ser-lhe-á pedido para desbloquear o telemóvel através de uma conta de email.\n\n Tente novamente dentro de <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="3389829202093674267">"Código PIN do cartão SIM incorreto. Tem de contactar o seu operador para desbloquear o dispositivo."</string>
     <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="4314341367727055967">
-      <item quantity="one">Código PIN do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_0">%d</xliff:g> tentativa antes de precisar de contactar o seu operador para desbloquear o dispositivo.</item>
       <item quantity="other">Código PIN do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas.</item>
+      <item quantity="one">Código PIN do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_0">%d</xliff:g> tentativa antes de precisar de contactar o seu operador para desbloquear o dispositivo.</item>
     </plurals>
     <string name="kg_password_wrong_puk_code_dead" msgid="3329017604125179374">"Cartão SIM inutilizável. Contacte o seu operador."</string>
     <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="2287504898931957513">
-      <item quantity="one">Código PUK do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_0">%d</xliff:g> tentativa antes de o cartão SIM ficar permanentemente inutilizável.</item>
       <item quantity="other">Código PUK do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas antes de o cartão SIM ficar permanentemente inutilizável.</item>
+      <item quantity="one">Código PUK do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_0">%d</xliff:g> tentativa antes de o cartão SIM ficar permanentemente inutilizável.</item>
     </plurals>
     <string name="kg_password_pin_failed" msgid="8769990811451236223">"Falha ao introduzir o PIN do cartão SIM!"</string>
     <string name="kg_password_puk_failed" msgid="1331621440873439974">"Falha ao introduzir o PUK do cartão SIM!"</string>
@@ -123,16 +123,16 @@
     <string name="kg_prompt_reason_device_admin" msgid="3452168247888906179">"Dispositivo bloqueado pelo gestor"</string>
     <string name="kg_prompt_reason_user_request" msgid="8236951765212462286">"O dispositivo foi bloqueado manualmente"</string>
     <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="71299470072448533">
-      <item quantity="one">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_0">%d</xliff:g> hora. Confirme o padrão.</item>
       <item quantity="other">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_1">%d</xliff:g> horas. Confirme o padrão.</item>
+      <item quantity="one">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_0">%d</xliff:g> hora. Confirme o padrão.</item>
     </plurals>
     <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="34586942088144385">
-      <item quantity="one">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_0">%d</xliff:g> hora. Confirme o PIN.</item>
       <item quantity="other">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_1">%d</xliff:g> horas. Confirme o PIN.</item>
+      <item quantity="one">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_0">%d</xliff:g> hora. Confirme o PIN.</item>
     </plurals>
     <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="257297696215346527">
-      <item quantity="one">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_0">%d</xliff:g> hora. Confirme a palavra-passe.</item>
       <item quantity="other">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_1">%d</xliff:g> horas. Confirme a palavra-passe.</item>
+      <item quantity="one">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_0">%d</xliff:g> hora. Confirme a palavra-passe.</item>
     </plurals>
     <string name="fingerprint_not_recognized" msgid="348813995267914625">"Não reconhecido"</string>
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index 3dd0e6c..3a41681 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -367,4 +367,20 @@
     <!-- Fingerprint hint message when finger was not recognized.-->
     <string name="fingerprint_not_recognized">Not recognized</string>
 
+    <!-- Instructions telling the user remaining times when enter SIM PIN view.  -->
+    <plurals name="kg_password_default_pin_message">
+        <item quantity="one">Enter SIM PIN, you have <xliff:g id="number">%d</xliff:g> remaining
+attempt before you must contact your carrier to unlock your device.</item>
+        <item quantity="other">Enter SIM PIN, you have <xliff:g id="number">%d</xliff:g> remaining
+attempts.</item>
+    </plurals>
+
+    <!-- Instructions telling the user remaining times when enter SIM PUK view.  -->
+    <plurals name="kg_password_default_puk_message">
+        <item quantity="one">SIM is now disabled. Enter PUK code to continue. You have <xliff:g id="
+number">%d</xliff:g> remaining attempt before SIM becomes permanently unusable. Contact carrier for details.</item>
+        <item quantity="other">SIM is now disabled. Enter PUK code to continue. You have <xliff:g id="
+number">%d</xliff:g> remaining attempts before SIM becomes permanently unusable. Contact carrier for details.</item>
+    </plurals>
+
 </resources>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 581ac73..5770779 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -34,14 +34,14 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"বিজ্ঞপ্তিগুলি"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"ব্যাটারি কম"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> অবশিষ্ট আছে"</string>
-    <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> অবশিষ্ট আছে৷ ব্যাটারি সাশ্রয়কারী চালু আছে৷"</string>
+    <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> অবশিষ্ট আছে। ব্যাটারি সেভার চালু আছে।"</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB চার্জিং সমর্থিত নয়৷\nকেবলমাত্র সরবহারকৃত চার্জার ব্যবহার করুন৷"</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB চার্জিং সমর্থিত নয়।"</string>
     <string name="invalid_charger_text" msgid="5474997287953892710">"শুধুমাত্র সরবরাহকৃত চার্জার ব্যবহার করুন।"</string>
     <string name="battery_low_why" msgid="4553600287639198111">"সেটিংস"</string>
-    <string name="battery_saver_confirmation_title" msgid="5299585433050361634">"ব্যাটারি সঞ্চয়কারী চালু করবেন?"</string>
+    <string name="battery_saver_confirmation_title" msgid="2052100465684817154">"ব্যাটারি সেভার চালু করবেন?"</string>
     <string name="battery_saver_confirmation_ok" msgid="7507968430447930257">"চালু করুন"</string>
-    <string name="battery_saver_start_action" msgid="5576697451677486320">"ব্যাটারি সঞ্চয়কারী চালু"</string>
+    <string name="battery_saver_start_action" msgid="8187820911065797519">"ব্যাটারি সেভার চালু করুন"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"সেটিংস"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"ওয়াই-ফাই"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"স্বতঃ-ঘূর্ণায়মান স্ক্রিন"</string>
@@ -243,8 +243,6 @@
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"ডেট বিরতি দেওয়া হয়েছে"</string>
     <string name="data_usage_disabled_dialog" msgid="4919541636934603816">"আপনার সেট করা ডেটার সীমা ফুরিয়ে গেছে। আপনি এখন আর মোবাইল ডেটা ব্যবহার করতে পারবেন না।\n\nযদি আপনি আবার শুরু করেন, ডেটা ব্যবহারের জন্য মূল্য প্রযোজ্য হতে পারে।"</string>
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"পুনঃসূচনা করুন"</string>
-    <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"কোনো ইন্টারনেট সংযোগ নেই"</string>
-    <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"ওয়াই-ফাই সংযুক্ত হয়েছে"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS এর জন্য অনুসন্ধান করা হচ্ছে"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS এর দ্বারা সেট করা অবস্থান"</string>
     <string name="accessibility_location_active" msgid="2427290146138169014">"অবস্থান অনুরোধ সক্রিয় রয়েছে"</string>
@@ -401,9 +399,9 @@
     <string name="user_remove_user_title" msgid="4681256956076895559">"ব্যবহারকারী সরাবেন?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"এই ব্যবহারকারীর সমস্ত অ্যাপ্লিকেশান ও ডেটা মুছে ফেলা হবে।"</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"সরান"</string>
-    <string name="battery_saver_notification_title" msgid="237918726750955859">"ব্যাটারি সেভার চালু রয়েছে"</string>
+    <string name="battery_saver_notification_title" msgid="8614079794522291840">"ব্যাটারি সেভার চালু আছে"</string>
     <string name="battery_saver_notification_text" msgid="820318788126672692">"কার্য-সম্পাদনা ও পশ্চাদপট ডেটাকে কমিয়ে দেয়"</string>
-    <string name="battery_saver_notification_action_text" msgid="109158658238110382">"ব্যাটারি সঞ্চয়কারী বন্ধ করুন"</string>
+    <string name="battery_saver_notification_action_text" msgid="132118784269455533">"ব্যাটারি সেভার বন্ধ করুন"</string>
     <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> আপনার স্ক্রীনে দেখানো সব কিছু ক্যাপচার করা শুরু করবে।"</string>
     <string name="media_projection_remember_text" msgid="3103510882172746752">"আর দেখাবেন না"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"সবকিছু সাফ করুন"</string>
@@ -582,8 +580,8 @@
       <item quantity="other">%d মিনিট</item>
     </plurals>
     <string name="battery_panel_title" msgid="7944156115535366613">"ব্যাটারির ব্যবহার"</string>
-    <string name="battery_detail_charging_summary" msgid="4055327085770378335">"চার্জ করার সময় ব্যাটারি সেভার কাজ করে না"</string>
-    <string name="battery_detail_switch_title" msgid="8763441006881907058">"ব্যাটারি সেভার"</string>
+    <string name="battery_detail_charging_summary" msgid="1279095653533044008">"চার্জ করার সময় ব্যাটারি সেভার উপলব্ধ নয়"</string>
+    <string name="battery_detail_switch_title" msgid="6285872470260795421">"ব্যাটারি সেভার"</string>
     <string name="battery_detail_switch_summary" msgid="9049111149407626804">"কার্য-সম্পাদনা ও পশ্চাদপট ডেটাকে কমিয়ে দেয়"</string>
     <string name="keyboard_key_button_template" msgid="6230056639734377300">"<xliff:g id="NAME">%1$s</xliff:g> বোতাম"</string>
     <string name="keyboard_key_home" msgid="2243500072071305073">"হোম"</string>
@@ -732,10 +730,10 @@
     <string name="pip_skip_to_prev" msgid="1955311326688637914">"পিছনে যাওয়ার জন্য এড়িয়ে যান"</string>
     <string name="thermal_shutdown_title" msgid="4458304833443861111">"আপনার ফোন গরম হওয়ার জন্য বন্ধ হয়ে গেছে"</string>
     <string name="thermal_shutdown_message" msgid="9006456746902370523">"আপনার ফোন এখন ঠিক-ঠাক চলছে"</string>
-    <string name="thermal_shutdown_dialog_message" msgid="566347880005304139">"আপনার ফোন খুব বেশি গরম হয়েছিল বলে ঠান্ডা হওয়ার জন্য বন্ধ হয়ে গেছে। আপনার ফোন ঠিক-ঠাক ভাবে চলছে না।\n\nআপনার ফোন খুব বেশি গরম হয়ে যাবে যদি আপনি:\n	•এমন অ্যাপ ব্যবহার করলে যেটি আপনার ডিভাইসের রিসোর্স বেশি ব্যবহার করে (যেমন গেমিং, ভিডিও বা নেভিগেশন অ্যাপ)\n	• বড় ফাইল ডাউনলোড বা আপলোড করলে\n	• বেশি তাপমাত্রায় আপনার ফোন ব্যবহার করলে"</string>
+    <string name="thermal_shutdown_dialog_message" msgid="566347880005304139">"আপনার ফোন খুব বেশি গরম হয়েছিল বলে ঠাণ্ডা হওয়ার জন্য বন্ধ হয়ে গেছে। আপনার ফোন ঠিক-ঠাক ভাবে চলছে না।\n\nআপনার ফোন খুব বেশি গরম হয়ে যাবে যদি আপনি:\n	•এমন অ্যাপ ব্যবহার করলে যেটি আপনার ডিভাইসের রিসোর্স বেশি ব্যবহার করে (যেমন গেমিং, ভিডিও বা নেভিগেশন অ্যাপ)\n	• বড় ফাইল ডাউনলোড বা আপলোড করলে\n	• বেশি তাপমাত্রায় আপনার ফোন ব্যবহার করলে"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"ফোনটি গরম হচ্ছে"</string>
-    <string name="high_temp_notif_message" msgid="5642466103153429279">"ফোনটি ঠান্ডা হওয়ার সময় কিছু বৈশিষ্ট্য সীমিত হতে পারে"</string>
-    <string name="high_temp_dialog_message" msgid="6840700639374113553">"আপনার ফোনটি নিজে থেকেই ঠান্ডা হওয়ার চেষ্টা করবে৷ আপনি তবুও আপনার ফোন ব্যবহার করতে পারেন, কিন্তু এটি একটু ধীরে চলতে পারে৷\n\nআপনার ফোনটি পুরোপুরি ঠান্ডা হয়ে গেলে এটি স্বাভাবিকভাবে চলবে৷"</string>
+    <string name="high_temp_notif_message" msgid="5642466103153429279">"ফোনটি ঠাণ্ডা হওয়ার সময় কিছু বৈশিষ্ট্য সীমিত হতে পারে"</string>
+    <string name="high_temp_dialog_message" msgid="6840700639374113553">"আপনার ফোনটি নিজে থেকেই ঠাণ্ডা হওয়ার চেষ্টা করবে৷ আপনি তবুও আপনার ফোন ব্যবহার করতে পারেন, কিন্তু এটি একটু ধীরে চলতে পারে৷\n\nআপনার ফোনটি পুরোপুরি ঠাণ্ডা হয়ে গেলে এটি স্বাভাবিকভাবে চলবে৷"</string>
     <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"বাঁদিকের শর্টকাট"</string>
     <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"ডানদিকের শর্টকাট"</string>
     <string name="lockscreen_unlock_left" msgid="2043092136246951985">"বাঁদিকের শর্টকাট দিয়েও আনলক করা যায়"</string>
@@ -758,7 +756,8 @@
     <string name="instant_apps" msgid="6647570248119804907">"ঝটপট অ্যাপ"</string>
     <string name="instant_apps_message" msgid="8116608994995104836">"ঝটপট অ্যাপ ইনস্টল করার প্রয়োজন হয় না।"</string>
     <string name="app_info" msgid="6856026610594615344">"অ্যাপের তথ্য"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"ওয়েবে যান"</string>
+    <!-- no translation found for go_to_web (2650669128861626071) -->
+    <skip />
     <string name="mobile_data" msgid="7094582042819250762">"মোবাইল ডেটা"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"ওয়াই ফাই বন্ধ আছে"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"ব্লুটুথ বন্ধ আছে"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 601d8e3..530c1a8 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -339,9 +339,9 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Podjela po horizontali"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Podjela po vertikali"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Prilagođena podjela"</string>
-    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Podijeli ekran nagore"</string>
-    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Podijeli ekran nalijevo"</string>
-    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Podijeli ekran nadesno"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Dijeli ekran nagore"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Dijeli ekran nalijevo"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Dijeli ekran nadesno"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Napunjeno"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Punjenje"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Do kraja punjenja preostalo <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
@@ -764,7 +764,8 @@
     <string name="instant_apps" msgid="6647570248119804907">"Instant-aplikacije"</string>
     <string name="instant_apps_message" msgid="8116608994995104836">"Za instant aplikacije nije potrebna instalacija"</string>
     <string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Idite na internet"</string>
+    <!-- no translation found for go_to_web (2650669128861626071) -->
+    <skip />
     <string name="mobile_data" msgid="7094582042819250762">"Mobilni podaci"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi veza je isključena"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth je isključen"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index cd1f057..d107fea 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -756,7 +756,8 @@
     <string name="instant_apps" msgid="6647570248119804907">"برنامه‌های فوری"</string>
     <string name="instant_apps_message" msgid="8116608994995104836">"برنامه‌های فوری نیاز به نصب ندارند."</string>
     <string name="app_info" msgid="6856026610594615344">"اطلاعات برنامه"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"رفتن به وب"</string>
+    <!-- no translation found for go_to_web (2650669128861626071) -->
+    <skip />
     <string name="mobile_data" msgid="7094582042819250762">"داده تلفن همراه"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"‏Wi-Fi خاموش است"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"بلوتوث خاموش است"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 075edf1..b4709bb 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -756,7 +756,8 @@
     <string name="instant_apps" msgid="6647570248119804907">"Aplikasi Instan"</string>
     <string name="instant_apps_message" msgid="8116608994995104836">"Aplikasi instan tidak perlu diinstal."</string>
     <string name="app_info" msgid="6856026610594615344">"Info aplikasi"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Buka di web"</string>
+    <!-- no translation found for go_to_web (2650669128861626071) -->
+    <skip />
     <string name="mobile_data" msgid="7094582042819250762">"Data seluler"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi nonaktif"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth nonaktif"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 1b80410..e871c6a 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -756,7 +756,8 @@
     <string name="instant_apps" msgid="6647570248119804907">"მყისიერი აპები"</string>
     <string name="instant_apps_message" msgid="8116608994995104836">"მყისიერი აპები ინსტალაციას არ საჭიროებს."</string>
     <string name="app_info" msgid="6856026610594615344">"აპის შესახებ"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"ვებზე გადასვლა"</string>
+    <!-- no translation found for go_to_web (2650669128861626071) -->
+    <skip />
     <string name="mobile_data" msgid="7094582042819250762">"მობილური ინტერნეტი"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi გამორთულია"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth გამორთულია"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index ec4e082..b5b3475 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -26,8 +26,8 @@
     <string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Os ecrãs recentes aparecem aqui"</string>
     <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Ignorar aplicações recentes"</string>
     <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
-      <item quantity="one">1 ecrã na Vista geral</item>
       <item quantity="other">%d ecrãs na Vista geral</item>
+      <item quantity="one">1 ecrã na Vista geral</item>
     </plurals>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Sem notificações"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Em curso"</string>
@@ -249,8 +249,8 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Limpar todas as notificações."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
-      <item quantity="one">Mais <xliff:g id="NUMBER_0">%s</xliff:g> notificação no grupo.</item>
       <item quantity="other">Mais <xliff:g id="NUMBER_1">%s</xliff:g> notificações no grupo.</item>
+      <item quantity="one">Mais <xliff:g id="NUMBER_0">%s</xliff:g> notificação no grupo.</item>
     </plurals>
     <string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Definições de notificação"</string>
     <string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Definições do <xliff:g id="APP_NAME">%s</xliff:g>"</string>
@@ -551,13 +551,13 @@
     <string name="notification_default_channel_desc" msgid="2506053815870808359">"Esta aplicação não tem categorias de notificação"</string>
     <string name="notification_unblockable_desc" msgid="3561016061737896906">"Não é possível desativar as notificações desta aplicação"</string>
     <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">1 de <xliff:g id="NUMBER_0">%s</xliff:g> categoria de notificação desta aplicação</item>
       <item quantity="other">1 de <xliff:g id="NUMBER_1">%s</xliff:g> categorias de notificação desta aplicação</item>
+      <item quantity="one">1 de <xliff:g id="NUMBER_0">%s</xliff:g> categoria de notificação desta aplicação</item>
     </plurals>
     <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
     <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> e mais <xliff:g id="NUMBER_2">%3$d</xliff:g></item>
       <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> e mais <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
+      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> e mais <xliff:g id="NUMBER_2">%3$d</xliff:g></item>
     </plurals>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Controlos de notificações da aplicação <xliff:g id="APP_NAME">%1$s</xliff:g> abertos"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Controlos de notificações da aplicação <xliff:g id="APP_NAME">%1$s</xliff:g> fechados"</string>
@@ -572,12 +572,12 @@
     <string name="snooze_undo" msgid="6074877317002985129">"ANULAR"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Suspensa por <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <plurals name="snoozeHourOptions" formatted="false" msgid="2124335842674413030">
-      <item quantity="one">%d hora</item>
       <item quantity="other">%d horas</item>
+      <item quantity="one">%d hora</item>
     </plurals>
     <plurals name="snoozeMinuteOptions" formatted="false" msgid="4127251700591510196">
-      <item quantity="one">%d minuto</item>
       <item quantity="other">%d minutos</item>
+      <item quantity="one">%d minuto</item>
     </plurals>
     <string name="battery_panel_title" msgid="7944156115535366613">"Utiliz. da bateria"</string>
     <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Poupança de bateria não disponível durante o carregamento"</string>
@@ -756,7 +756,8 @@
     <string name="instant_apps" msgid="6647570248119804907">"Aplicações instantâneas"</string>
     <string name="instant_apps_message" msgid="8116608994995104836">"As Aplicações instantâneas não requerem instalação."</string>
     <string name="app_info" msgid="6856026610594615344">"Informações da aplicação"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Aceder à Web"</string>
+    <!-- no translation found for go_to_web (2650669128861626071) -->
+    <skip />
     <string name="mobile_data" msgid="7094582042819250762">"Dados móveis"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi desativado"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth desativado"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 5b9ff78..95cd2d0 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -770,7 +770,8 @@
     <string name="instant_apps" msgid="6647570248119804907">"Додатки з миттєвим запуском"</string>
     <string name="instant_apps_message" msgid="8116608994995104836">"Додатки з миттєвим запуском не потрібно встановлювати."</string>
     <string name="app_info" msgid="6856026610594615344">"Про додаток"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Перейти на веб-сайт"</string>
+    <!-- no translation found for go_to_web (2650669128861626071) -->
+    <skip />
     <string name="mobile_data" msgid="7094582042819250762">"Мобільний трафік"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi вимкнено"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth вимкнено"</string>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
index 432b406..6e0b56e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
@@ -53,8 +53,13 @@
     private ProgressDialog mSimUnlockProgressDialog = null;
     private CheckSimPin mCheckSimPinThread;
 
+    // Below flag is set to true during power-up or when a new SIM card inserted on device.
+    // When this is true and when SIM card is PIN locked state, on PIN lock screen, message would
+    // be displayed to inform user about the number of remaining PIN attempts left.
+    private boolean mShowDefaultMessage = true;
+    private int mRemainingAttempts = -1;
     private AlertDialog mRemainingAttemptsDialog;
-    private int mSubId;
+    private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
     private ImageView mSimImageView;
 
     KeyguardUpdateMonitorCallback mUpdateMonitorCallback = new KeyguardUpdateMonitorCallback() {
@@ -91,34 +96,71 @@
     public void resetState() {
         super.resetState();
         if (DEBUG) Log.v(TAG, "Resetting state");
-        KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
-        mSubId = monitor.getNextSubIdForState(IccCardConstants.State.PIN_REQUIRED);
-        boolean isEsimLocked = KeyguardEsimArea.isEsimLocked(mContext, mSubId);
-        if (SubscriptionManager.isValidSubscriptionId(mSubId)) {
-            int count = TelephonyManager.getDefault().getSimCount();
-            Resources rez = getResources();
-            String msg;
-            int color = Color.WHITE;
-            if (count < 2) {
-                msg = rez.getString(R.string.kg_sim_pin_instructions);
-            } else {
-                SubscriptionInfo info = monitor.getSubscriptionInfoForSubId(mSubId);
-                CharSequence displayName = info != null ? info.getDisplayName() : ""; // don't crash
-                msg = rez.getString(R.string.kg_sim_pin_instructions_multi, displayName);
-                if (info != null) {
-                    color = info.getIconTint();
-                }
-            }
-            if (isEsimLocked) {
-                msg = msg + " " + rez.getString(R.string.kg_sim_lock_instructions_esim);
-            }
-            mSecurityMessageDisplay.setMessage(msg);
-            mSimImageView.setImageTintList(ColorStateList.valueOf(color));
+        handleSubInfoChangeIfNeeded();
+        if (mShowDefaultMessage) {
+            showDefaultMessage();
         }
+        boolean isEsimLocked = KeyguardEsimArea.isEsimLocked(mContext, mSubId);
+
         KeyguardEsimArea esimButton = findViewById(R.id.keyguard_esim_area);
         esimButton.setVisibility(isEsimLocked ? View.VISIBLE : View.GONE);
     }
 
+    private void showDefaultMessage() {
+        if (mRemainingAttempts >= 0) {
+            mSecurityMessageDisplay.setMessage(getPinPasswordErrorMessage(
+                    mRemainingAttempts, true));
+            return;
+        }
+
+        boolean isEsimLocked = KeyguardEsimArea.isEsimLocked(mContext, mSubId);
+        int count = TelephonyManager.getDefault().getSimCount();
+        Resources rez = getResources();
+        String msg;
+        int color = Color.WHITE;
+        if (count < 2) {
+            msg = rez.getString(R.string.kg_sim_pin_instructions);
+        } else {
+            SubscriptionInfo info = KeyguardUpdateMonitor.getInstance(mContext).
+                    getSubscriptionInfoForSubId(mSubId);
+            CharSequence displayName = info != null ? info.getDisplayName() : ""; // don't crash
+            msg = rez.getString(R.string.kg_sim_pin_instructions_multi, displayName);
+            if (info != null) {
+                color = info.getIconTint();
+            }
+        }
+
+        if (isEsimLocked) {
+            msg = msg + " " + rez.getString(R.string.kg_sim_lock_instructions_esim);
+        }
+
+        mSecurityMessageDisplay.setMessage(msg);
+        mSimImageView.setImageTintList(ColorStateList.valueOf(color));
+
+        // Sending empty PIN here to query the number of remaining PIN attempts
+        new CheckSimPin("", mSubId) {
+            void onSimCheckResponse(final int result, final int attemptsRemaining) {
+                Log.d(LOG_TAG, "onSimCheckResponse " + " dummy One result" + result +
+                        " attemptsRemaining=" + attemptsRemaining);
+                if (attemptsRemaining >= 0) {
+                    mRemainingAttempts = attemptsRemaining;
+                    mSecurityMessageDisplay.setMessage(
+                            getPinPasswordErrorMessage(attemptsRemaining, true));
+                }
+            }
+        }.start();
+    }
+
+    private void handleSubInfoChangeIfNeeded() {
+        KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
+        int subId = monitor.getNextSubIdForState(IccCardConstants.State.PIN_REQUIRED);
+        if (subId != mSubId && SubscriptionManager.isValidSubscriptionId(subId)) {
+            mSubId = subId;
+            mShowDefaultMessage = true;
+            mRemainingAttempts = -1;
+        }
+    }
+
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
@@ -131,17 +173,19 @@
         return 0;
     }
 
-    private String getPinPasswordErrorMessage(int attemptsRemaining) {
+    private String getPinPasswordErrorMessage(int attemptsRemaining, boolean isDefault) {
         String displayMessage;
-
+        int msgId;
         if (attemptsRemaining == 0) {
             displayMessage = getContext().getString(R.string.kg_password_wrong_pin_code_pukked);
         } else if (attemptsRemaining > 0) {
+            msgId = isDefault ? R.plurals.kg_password_default_pin_message :
+                     R.plurals.kg_password_wrong_pin_code;
             displayMessage = getContext().getResources()
-                    .getQuantityString(R.plurals.kg_password_wrong_pin_code, attemptsRemaining,
-                            attemptsRemaining);
+                    .getQuantityString(msgId, attemptsRemaining, attemptsRemaining);
         } else {
-            displayMessage = getContext().getString(R.string.kg_password_pin_failed);
+            msgId = isDefault ? R.string.kg_sim_pin_instructions : R.string.kg_password_pin_failed;
+            displayMessage = getContext().getString(msgId);
         }
         if (DEBUG) Log.d(LOG_TAG, "getPinPasswordErrorMessage:"
                 + " attemptsRemaining=" + attemptsRemaining + " displayMessage=" + displayMessage);
@@ -252,7 +296,7 @@
     }
 
     private Dialog getSimRemainingAttemptsDialog(int remaining) {
-        String msg = getPinPasswordErrorMessage(remaining);
+        String msg = getPinPasswordErrorMessage(remaining, false);
         if (mRemainingAttemptsDialog == null) {
             Builder builder = new AlertDialog.Builder(mContext);
             builder.setMessage(msg);
@@ -288,6 +332,7 @@
                     post(new Runnable() {
                         @Override
                         public void run() {
+                            mRemainingAttempts = attemptsRemaining;
                             if (mSimUnlockProgressDialog != null) {
                                 mSimUnlockProgressDialog.hide();
                             }
@@ -296,8 +341,13 @@
                             if (result == PhoneConstants.PIN_RESULT_SUCCESS) {
                                 KeyguardUpdateMonitor.getInstance(getContext())
                                         .reportSimUnlocked(mSubId);
-                                mCallback.dismiss(true, KeyguardUpdateMonitor.getCurrentUser());
+                                mRemainingAttempts = -1;
+                                mShowDefaultMessage = true;
+                                if (mCallback != null) {
+                                    mCallback.dismiss(true, KeyguardUpdateMonitor.getCurrentUser());
+                                }
                             } else {
+                                mShowDefaultMessage = false;
                                 if (result == PhoneConstants.PIN_PASSWORD_INCORRECT) {
                                     if (attemptsRemaining <= 2) {
                                         // this is getting critical - show dialog
@@ -305,7 +355,7 @@
                                     } else {
                                         // show message
                                         mSecurityMessageDisplay.setMessage(
-                                                getPinPasswordErrorMessage(attemptsRemaining));
+                                                getPinPasswordErrorMessage(attemptsRemaining, false));
                                     }
                                 } else {
                                     // "PIN operation failed!" - no idea what this was and no way to
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
index 7f79008..876d170 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
@@ -52,11 +52,17 @@
 
     private ProgressDialog mSimUnlockProgressDialog = null;
     private CheckSimPuk mCheckSimPukThread;
+
+    // Below flag is set to true during power-up or when a new SIM card inserted on device.
+    // When this is true and when SIM card is PUK locked state, on PIN lock screen, message would
+    // be displayed to inform user about the number of remaining PUK attempts left.
+    private boolean mShowDefaultMessage = true;
+    private int mRemainingAttempts = -1;
     private String mPukText;
     private String mPinText;
     private StateMachine mStateMachine = new StateMachine();
     private AlertDialog mRemainingAttemptsDialog;
-    private int mSubId;
+    private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
     private ImageView mSimImageView;
 
     KeyguardUpdateMonitorCallback mUpdateMonitorCallback = new KeyguardUpdateMonitorCallback() {
@@ -132,34 +138,17 @@
             }
         }
 
+
         void reset() {
             mPinText="";
             mPukText="";
             state = ENTER_PUK;
-            KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
-            mSubId = monitor.getNextSubIdForState(IccCardConstants.State.PUK_REQUIRED);
-            boolean isEsimLocked = KeyguardEsimArea.isEsimLocked(mContext, mSubId);
-            if (SubscriptionManager.isValidSubscriptionId(mSubId)) {
-                int count = TelephonyManager.getDefault().getSimCount();
-                Resources rez = getResources();
-                String msg;
-                int color = Color.WHITE;
-                if (count < 2) {
-                    msg = rez.getString(R.string.kg_puk_enter_puk_hint);
-                } else {
-                    SubscriptionInfo info = monitor.getSubscriptionInfoForSubId(mSubId);
-                    CharSequence displayName = info != null ? info.getDisplayName() : "";
-                    msg = rez.getString(R.string.kg_puk_enter_puk_hint_multi, displayName);
-                    if (info != null) {
-                        color = info.getIconTint();
-                    }
-                }
-                if (isEsimLocked) {
-                    msg = msg + " " + rez.getString(R.string.kg_sim_lock_instructions_esim);
-                }
-                mSecurityMessageDisplay.setMessage(msg);
-                mSimImageView.setImageTintList(ColorStateList.valueOf(color));
+            handleSubInfoChangeIfNeeded();
+            if (mShowDefaultMessage) {
+                showDefaultMessage();
             }
+            boolean isEsimLocked = KeyguardEsimArea.isEsimLocked(mContext, mSubId);
+
             KeyguardEsimArea esimButton = findViewById(R.id.keyguard_esim_area);
             esimButton.setVisibility(isEsimLocked ? View.VISIBLE : View.GONE);
             mPasswordEntry.requestFocus();
@@ -168,23 +157,79 @@
 
     }
 
+    private void showDefaultMessage() {
+        if (mRemainingAttempts >= 0) {
+            mSecurityMessageDisplay.setMessage(getPukPasswordErrorMessage(
+                    mRemainingAttempts, true));
+            return;
+        }
+
+        boolean isEsimLocked = KeyguardEsimArea.isEsimLocked(mContext, mSubId);
+        int count = TelephonyManager.getDefault().getSimCount();
+        Resources rez = getResources();
+        String msg;
+        int color = Color.WHITE;
+        if (count < 2) {
+            msg = rez.getString(R.string.kg_puk_enter_puk_hint);
+        } else {
+            SubscriptionInfo info = KeyguardUpdateMonitor.getInstance(mContext).
+                    getSubscriptionInfoForSubId(mSubId);
+            CharSequence displayName = info != null ? info.getDisplayName() : "";
+            msg = rez.getString(R.string.kg_puk_enter_puk_hint_multi, displayName);
+            if (info != null) {
+                color = info.getIconTint();
+            }
+        }
+        if (isEsimLocked) {
+            msg = msg + " " + rez.getString(R.string.kg_sim_lock_instructions_esim);
+        }
+        mSecurityMessageDisplay.setMessage(msg);
+        mSimImageView.setImageTintList(ColorStateList.valueOf(color));
+
+        // Sending empty PUK here to query the number of remaining PIN attempts
+        new CheckSimPuk("", "", mSubId) {
+            void onSimLockChangedResponse(final int result, final int attemptsRemaining) {
+                Log.d(LOG_TAG, "onSimCheckResponse " + " dummy One result" + result +
+                        " attemptsRemaining=" + attemptsRemaining);
+                if (attemptsRemaining >= 0) {
+                    mRemainingAttempts = attemptsRemaining;
+                    mSecurityMessageDisplay.setMessage(
+                            getPukPasswordErrorMessage(attemptsRemaining, true));
+                }
+            }
+        }.start();
+    }
+
+    private void handleSubInfoChangeIfNeeded() {
+        KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
+        int subId = monitor.getNextSubIdForState(IccCardConstants.State.PUK_REQUIRED);
+        if (subId != mSubId && SubscriptionManager.isValidSubscriptionId(subId)) {
+            mSubId = subId;
+            mShowDefaultMessage = true;
+            mRemainingAttempts = -1;
+        }
+    }
+
     @Override
     protected int getPromtReasonStringRes(int reason) {
         // No message on SIM Puk
         return 0;
     }
 
-    private String getPukPasswordErrorMessage(int attemptsRemaining) {
+    private String getPukPasswordErrorMessage(int attemptsRemaining, boolean isDefault) {
         String displayMessage;
 
         if (attemptsRemaining == 0) {
             displayMessage = getContext().getString(R.string.kg_password_wrong_puk_code_dead);
         } else if (attemptsRemaining > 0) {
+            int msgId = isDefault ? R.plurals.kg_password_default_puk_message :
+                    R.plurals.kg_password_wrong_puk_code;
             displayMessage = getContext().getResources()
-                    .getQuantityString(R.plurals.kg_password_wrong_puk_code, attemptsRemaining,
-                            attemptsRemaining);
+                    .getQuantityString(msgId, attemptsRemaining, attemptsRemaining);
         } else {
-            displayMessage = getContext().getString(R.string.kg_password_puk_failed);
+            int msgId = isDefault ? R.string.kg_puk_enter_puk_hint :
+                    R.string.kg_password_puk_failed;
+            displayMessage = getContext().getString(msgId);
         }
         if (DEBUG) Log.d(LOG_TAG, "getPukPasswordErrorMessage:"
                 + " attemptsRemaining=" + attemptsRemaining + " displayMessage=" + displayMessage);
@@ -303,7 +348,7 @@
     }
 
     private Dialog getPukRemainingAttemptsDialog(int remaining) {
-        String msg = getPukPasswordErrorMessage(remaining);
+        String msg = getPukPasswordErrorMessage(remaining, false);
         if (mRemainingAttemptsDialog == null) {
             AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
             builder.setMessage(msg);
@@ -359,16 +404,25 @@
                             if (result == PhoneConstants.PIN_RESULT_SUCCESS) {
                                 KeyguardUpdateMonitor.getInstance(getContext())
                                         .reportSimUnlocked(mSubId);
-                                mCallback.dismiss(true, KeyguardUpdateMonitor.getCurrentUser());
+                                mRemainingAttempts = -1;
+                                mShowDefaultMessage = true;
+                                if (mCallback != null) {
+                                    mCallback.dismiss(true, KeyguardUpdateMonitor.getCurrentUser());
+                                }
                             } else {
+                                mShowDefaultMessage = false;
                                 if (result == PhoneConstants.PIN_PASSWORD_INCORRECT) {
+                                    // show message
+                                    mSecurityMessageDisplay.setMessage(getPukPasswordErrorMessage(
+                                            attemptsRemaining, false));
                                     if (attemptsRemaining <= 2) {
                                         // this is getting critical - show dialog
                                         getPukRemainingAttemptsDialog(attemptsRemaining).show();
                                     } else {
                                         // show message
                                         mSecurityMessageDisplay.setMessage(
-                                                getPukPasswordErrorMessage(attemptsRemaining));
+                                                getPukPasswordErrorMessage(
+                                                attemptsRemaining, false));
                                     }
                                 } else {
                                     mSecurityMessageDisplay.setMessage(getContext().getString(
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 5d4ddf0..b2a0ce5 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -715,14 +715,14 @@
             @Nullable ArrayList<String> changedDatasetIds,
             @Nullable ArrayList<AutofillId> manuallyFilledFieldIds,
             @Nullable ArrayList<ArrayList<String>> manuallyFilledDatasetIds,
-            @NonNull ArrayList<AutofillId> detectedFieldIdsList,
-            @NonNull ArrayList<Match> detectedMatchesList) {
+            @Nullable ArrayList<AutofillId> detectedFieldIdsList,
+            @Nullable ArrayList<Match> detectedMatchesList) {
 
         synchronized (mLock) {
             if (isValidEventLocked("logDatasetNotSelected()", sessionId)) {
                 AutofillId[] detectedFieldsIds = null;
                 Match[] detectedMatches = null;
-                if (!detectedFieldIdsList.isEmpty()) {
+                if (detectedFieldIdsList != null) {
                     detectedFieldsIds = new AutofillId[detectedFieldIdsList.size()];
                     detectedFieldIdsList.toArray(detectedFieldsIds);
                     detectedMatches = new Match[detectedMatchesList.size()];
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index fc57a0d..dc35051 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -108,6 +108,8 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.service.vr.IVrManager;
+import android.service.vr.IVrStateCallbacks;
 import android.text.TextUtils;
 import android.text.style.SuggestionSpan;
 import android.util.ArrayMap;
@@ -189,6 +191,7 @@
     static final int MSG_CREATE_SESSION = 1050;
 
     static final int MSG_START_INPUT = 2000;
+    static final int MSG_START_VR_INPUT = 2010;
 
     static final int MSG_UNBIND_CLIENT = 3000;
     static final int MSG_BIND_CLIENT = 3010;
@@ -317,6 +320,28 @@
         }
     }
 
+    /**
+     * VR state callback.
+     * Listens for when VR mode finishes.
+     */
+    private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
+        @Override
+        public void onVrStateChanged(boolean enabled) {
+            if (!enabled) {
+                restoreNonVrImeFromSettingsNoCheck();
+            }
+        }
+    };
+
+    private void restoreNonVrImeFromSettingsNoCheck() {
+        // switch back to non-VR InputMethod from settings.
+        synchronized (mMethodMap) {
+            final String lastInputId = mSettings.getSelectedInputMethod();
+            setInputMethodLocked(lastInputId,
+                    mSettings.getSelectedInputMethodSubtypeId(lastInputId));
+        }
+    }
+
     static final class ClientState {
         final IInputMethodClient client;
         final IInputContext inputContext;
@@ -863,6 +888,30 @@
     }
 
     /**
+     * Start a VR InputMethod that matches IME with package name of {@param component}.
+     * Note: This method is called from {@link VrManager}.
+     */
+    private void startVrInputMethodNoCheck(@Nullable ComponentName component) {
+        if (component == null) {
+            // clear the current VR-only IME (if any) and restore normal IME.
+            restoreNonVrImeFromSettingsNoCheck();
+            return;
+        }
+
+        synchronized (mMethodMap) {
+            String packageName = component.getPackageName();
+            for (InputMethodInfo info : mMethodList) {
+                if (TextUtils.equals(info.getPackageName(), packageName) && info.isVrOnly()) {
+                    // set this is as current inputMethod without updating settings.
+                    setInputMethodEnabled(info.getId(), true);
+                    setInputMethodLocked(info.getId(), NOT_A_SUBTYPE_ID);
+                    break;
+                }
+            }
+        }
+    }
+
+    /**
      * Handles {@link Intent#ACTION_LOCALE_CHANGED}.
      *
      * <p>Note: For historical reasons, {@link Intent#ACTION_LOCALE_CHANGED} has been sent to all
@@ -1338,6 +1387,15 @@
         mFileManager = new InputMethodFileManager(mMethodMap, userId);
         mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked(
                 mSettings, context);
+        // Register VR-state listener.
+        IVrManager vrManager = (IVrManager) ServiceManager.getService(Context.VR_SERVICE);
+        if (vrManager != null) {
+            try {
+                vrManager.registerListener(mVrStateCallbacks);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to register VR mode state listener.");
+            }
+        }
     }
 
     private void resetDefaultImeLocked(Context context) {
@@ -1562,12 +1620,27 @@
 
     @Override
     public List<InputMethodInfo> getInputMethodList() {
+        return getInputMethodList(false /* isVrOnly */);
+    }
+
+    public List<InputMethodInfo> getVrInputMethodList() {
+        return getInputMethodList(true /* isVrOnly */);
+    }
+
+    private List<InputMethodInfo> getInputMethodList(final boolean isVrOnly) {
         // TODO: Make this work even for non-current users?
         if (!calledFromValidUser()) {
             return Collections.emptyList();
         }
         synchronized (mMethodMap) {
-            return new ArrayList<>(mMethodList);
+            ArrayList<InputMethodInfo> methodList = new ArrayList<>();
+            for (InputMethodInfo info : mMethodList) {
+
+                if (info.isVrOnly() == isVrOnly) {
+                    methodList.add(info);
+                }
+            }
+            return methodList;
         }
     }
 
@@ -3356,6 +3429,9 @@
             case MSG_SET_INTERACTIVE:
                 handleSetInteractive(msg.arg1 != 0);
                 return true;
+            case MSG_START_VR_INPUT:
+                startVrInputMethodNoCheck((ComponentName) msg.obj);
+                return true;
             case MSG_SWITCH_IME:
                 handleSwitchInputMethod(msg.arg1 != 0);
                 return true;
@@ -3876,8 +3952,12 @@
 
     private void setSelectedInputMethodAndSubtypeLocked(InputMethodInfo imi, int subtypeId,
             boolean setSubtypeOnly) {
-        // Update the history of InputMethod and Subtype
-        mSettings.saveCurrentInputMethodAndSubtypeToHistory(mCurMethodId, mCurrentSubtype);
+        // Updates to InputMethod are transient in VR mode. Its not included in history.
+        final boolean isVrInput = imi != null && imi.isVrOnly();
+        if (!isVrInput) {
+            // Update the history of InputMethod and Subtype
+            mSettings.saveCurrentInputMethodAndSubtypeToHistory(mCurMethodId, mCurrentSubtype);
+        }
 
         mCurUserActionNotificationSequenceNumber =
                 Math.max(mCurUserActionNotificationSequenceNumber + 1, 1);
@@ -3892,6 +3972,11 @@
                     mCurUserActionNotificationSequenceNumber, mCurClient));
         }
 
+        if (isVrInput) {
+            // Updates to InputMethod are transient in VR mode. Any changes to Settings are skipped.
+            return;
+        }
+
         // Set Subtype here
         if (imi == null || subtypeId < 0) {
             mSettings.putSelectedSubtype(NOT_A_SUBTYPE_ID);
@@ -4351,6 +4436,11 @@
             mHandler.removeMessages(MSG_HIDE_CURRENT_INPUT_METHOD);
             mHandler.sendEmptyMessage(MSG_HIDE_CURRENT_INPUT_METHOD);
         }
+
+        @Override
+        public void startVrInputMethodNoCheck(@Nullable ComponentName componentName) {
+            mHandler.sendMessage(mHandler.obtainMessage(MSG_START_VR_INPUT, componentName));
+        }
     }
 
     private static String imeWindowStatusToString(final int imeWindowVis) {
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
index 2d2424f..9bfdd0c 100644
--- a/services/core/java/com/android/server/am/ActivityDisplay.java
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -433,7 +433,9 @@
                         || !otherStack.affectedBySplitScreenResize()) {
                     continue;
                 }
-                otherStack.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+                otherStack.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
+                        false /* animate */, false /* showRecents */,
+                        false /* sendNonResizeableNotification */);
             }
         } finally {
             mSupervisor.mWindowManager.continueSurfaceLayout();
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 7b4703a..982380c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -10570,7 +10570,8 @@
                 if (toTop) {
                     stack.moveToFront("setTaskWindowingModeSplitScreenPrimary", task);
                 }
-                stack.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, animate, showRecents);
+                stack.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, animate, showRecents,
+                        true /* sendNonResizeableNotification */);
                 return windowingMode != task.getWindowingMode();
             } finally {
                 Binder.restoreCallingIdentity(ident);
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index edf9813..fcf9946 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -483,10 +483,12 @@
 
     @Override
     public void setWindowingMode(int windowingMode) {
-        setWindowingMode(windowingMode, false /* animate */, true /* showRecents */);
+        setWindowingMode(windowingMode, false /* animate */, true /* showRecents */,
+                true /* sendNonResizeableNotification */);
     }
 
-    void setWindowingMode(int preferredWindowingMode, boolean animate, boolean showRecents) {
+    void setWindowingMode(int preferredWindowingMode, boolean animate, boolean showRecents,
+            boolean sendNonResizeableNotification) {
         final int currentMode = getWindowingMode();
         final ActivityDisplay display = getDisplay();
         final TaskRecord topTask = topTask();
@@ -505,7 +507,8 @@
         final boolean alreadyInSplitScreenMode = display.hasSplitScreenPrimaryStack();
 
         // Take any required action due to us not supporting the preferred windowing mode.
-        if (windowingMode != preferredWindowingMode && isActivityTypeStandardOrUndefined()) {
+        if (sendNonResizeableNotification
+                && windowingMode != preferredWindowingMode && isActivityTypeStandardOrUndefined()) {
             if (alreadyInSplitScreenMode
                     && (preferredWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
                     || preferredWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY)) {
@@ -524,8 +527,9 @@
         final WindowManagerService wm = mService.mWindowManager;
         final ActivityRecord topActivity = getTopActivity();
 
-        if (windowingMode != WINDOWING_MODE_FULLSCREEN && topActivity != null
-                && topActivity.isNonResizableOrForcedResizable() && !topActivity.noDisplay) {
+        if (sendNonResizeableNotification && windowingMode != WINDOWING_MODE_FULLSCREEN
+                && topActivity != null && topActivity.isNonResizableOrForcedResizable()
+                && !topActivity.noDisplay) {
             // Inform the user that they are starting an app that may not work correctly in
             // multi-window mode.
             final String packageName = topActivity.appInfo.packageName;
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 9cd52d7..bdfd4bd 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -323,7 +323,7 @@
     private final BroadcastReceiver mAccountsUpdatedReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            EndPoint target = new EndPoint(null, null, context.getUserId());
+            EndPoint target = new EndPoint(null, null, getSendingUserId());
             updateRunningAccounts(target /* sync targets for user */);
         }
     };
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 8b2854c..f60cb06 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -9714,6 +9714,7 @@
         // them in the case where we're not upgrading or booting for the first time.
         String primaryCpuAbiFromSettings = null;
         String secondaryCpuAbiFromSettings = null;
+        boolean needToDeriveAbi = (scanFlags & SCAN_FIRST_BOOT_OR_UPGRADE) != 0;
 
         // writer
         synchronized (mPackages) {
@@ -9791,11 +9792,14 @@
                 }
             }
 
-            if ((scanFlags & SCAN_FIRST_BOOT_OR_UPGRADE) == 0) {
+            if (!needToDeriveAbi) {
                 PackageSetting foundPs = mSettings.getPackageLPr(pkg.packageName);
                 if (foundPs != null) {
                     primaryCpuAbiFromSettings = foundPs.primaryCpuAbiString;
                     secondaryCpuAbiFromSettings = foundPs.secondaryCpuAbiString;
+                } else {
+                    // when re-adding a system package failed after uninstalling updates.
+                    needToDeriveAbi = true;
                 }
             }
 
@@ -10011,7 +10015,7 @@
         final String cpuAbiOverride = deriveAbiOverride(pkg.cpuAbiOverride, pkgSetting);
 
         if ((scanFlags & SCAN_NEW_INSTALL) == 0) {
-            if ((scanFlags & SCAN_FIRST_BOOT_OR_UPGRADE) != 0) {
+            if (needToDeriveAbi) {
                 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "derivePackageAbi");
                 final boolean extractNativeLibs = !pkg.isLibrary();
                 derivePackageAbi(pkg, cpuAbiOverride, extractNativeLibs, mAppLib32InstallDir);
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 1f4e64e..7d55b68 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -59,6 +59,7 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import com.android.server.wm.WindowManagerInternal;
+import android.view.inputmethod.InputMethodManagerInternal;
 
 import com.android.internal.R;
 import com.android.internal.util.DumpUtils;
@@ -609,6 +610,14 @@
         }
 
         @Override
+        public void setVrInputMethod(ComponentName componentName) {
+            enforceCallerPermissionAnyOf(Manifest.permission.RESTRICTED_VR_ACCESS);
+            InputMethodManagerInternal imm =
+                    LocalServices.getService(InputMethodManagerInternal.class);
+            imm.startVrInputMethodNoCheck(componentName);
+        }
+
+        @Override
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 6467582..c371e88 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -21,6 +21,7 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 import static com.android.server.wm.proto.WindowContainerProto.CONFIGURATION_CONTAINER;
 import static com.android.server.wm.proto.WindowContainerProto.ORIENTATION;
+import static com.android.server.wm.proto.WindowContainerProto.VISIBLE;
 import static android.view.SurfaceControl.Transaction;
 
 import android.annotation.CallSuper;
@@ -809,6 +810,7 @@
         final long token = proto.start(fieldId);
         super.writeToProto(proto, CONFIGURATION_CONTAINER, trim);
         proto.write(ORIENTATION, mOrientation);
+        proto.write(VISIBLE, isVisible());
         proto.end(token);
     }
 
diff --git a/services/net/java/android/net/ip/IpClient.java b/services/net/java/android/net/ip/IpClient.java
index 70983c8..5c58cdb 100644
--- a/services/net/java/android/net/ip/IpClient.java
+++ b/services/net/java/android/net/ip/IpClient.java
@@ -163,10 +163,10 @@
     // TODO: Find an lighter weight approach.
     private class LoggingCallbackWrapper extends Callback {
         private static final String PREFIX = "INVOKE ";
-        private Callback mCallback;
+        private final Callback mCallback;
 
         public LoggingCallbackWrapper(Callback callback) {
-            mCallback = callback;
+            mCallback = (callback != null) ? callback : new Callback();
         }
 
         private void log(String msg) {
@@ -1273,6 +1273,7 @@
             stopAllIP();
 
             resetLinkProperties();
+            mCallback.onLinkPropertiesChange(new LinkProperties(mLinkProperties));
             if (mStartTimeMillis > 0) {
                 recordMetric(IpManagerEvent.COMPLETE_LIFECYCLE);
                 mStartTimeMillis = 0;
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
index 51c805d..cd3fdee 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
@@ -66,6 +66,7 @@
     private SoundTriggerDbHelper mDbHelper;
     private SoundTriggerHelper mSoundTriggerHelper;
     private final TreeMap<UUID, SoundModel> mLoadedModels;
+    private Object mCallbacksLock;
     private final TreeMap<UUID, LocalSoundTriggerRecognitionStatusCallback> mIntentCallbacks;
     private PowerManager.WakeLock mWakelock;
 
@@ -75,6 +76,7 @@
         mServiceStub = new SoundTriggerServiceStub();
         mLocalSoundTriggerService = new LocalSoundTriggerService(context);
         mLoadedModels = new TreeMap<UUID, SoundModel>();
+        mCallbacksLock = new Object();
         mIntentCallbacks = new TreeMap<UUID, LocalSoundTriggerRecognitionStatusCallback>();
         mLock = new Object();
     }
@@ -211,7 +213,9 @@
                 // don't know if the other model is loaded.
                 if (oldModel != null && !oldModel.equals(soundModel)) {
                     mSoundTriggerHelper.unloadGenericSoundModel(soundModel.uuid);
-                    mIntentCallbacks.remove(soundModel.uuid);
+                    synchronized (mCallbacksLock) {
+                        mIntentCallbacks.remove(soundModel.uuid);
+                    }
                 }
                 mLoadedModels.put(soundModel.uuid, soundModel);
             }
@@ -240,7 +244,9 @@
                 // don't know if the other model is loaded.
                 if (oldModel != null && !oldModel.equals(soundModel)) {
                     mSoundTriggerHelper.unloadKeyphraseSoundModel(soundModel.keyphrases[0].id);
-                    mIntentCallbacks.remove(soundModel.uuid);
+                    synchronized (mCallbacksLock) {
+                        mIntentCallbacks.remove(soundModel.uuid);
+                    }
                 }
                 mLoadedModels.put(soundModel.uuid, soundModel);
             }
@@ -262,8 +268,10 @@
                     Slog.e(TAG, soundModelId + " is not loaded");
                     return STATUS_ERROR;
                 }
-                LocalSoundTriggerRecognitionStatusCallback callback = mIntentCallbacks.get(
-                        soundModelId.getUuid());
+                LocalSoundTriggerRecognitionStatusCallback callback = null;
+                synchronized (mCallbacksLock) {
+                    callback = mIntentCallbacks.get(soundModelId.getUuid());
+                }
                 if (callback != null) {
                     Slog.e(TAG, soundModelId + " is already running");
                     return STATUS_ERROR;
@@ -291,7 +299,9 @@
                     Slog.e(TAG, "Failed to start model: " + ret);
                     return ret;
                 }
-                mIntentCallbacks.put(soundModelId.getUuid(), callback);
+                synchronized (mCallbacksLock) {
+                    mIntentCallbacks.put(soundModelId.getUuid(), callback);
+                }
             }
             return STATUS_OK;
         }
@@ -310,8 +320,10 @@
                     Slog.e(TAG, soundModelId + " is not loaded");
                     return STATUS_ERROR;
                 }
-                LocalSoundTriggerRecognitionStatusCallback callback = mIntentCallbacks.get(
-                        soundModelId.getUuid());
+                LocalSoundTriggerRecognitionStatusCallback callback = null;
+                synchronized (mCallbacksLock) {
+                     callback = mIntentCallbacks.get(soundModelId.getUuid());
+                }
                 if (callback == null) {
                     Slog.e(TAG, soundModelId + " is not running");
                     return STATUS_ERROR;
@@ -334,7 +346,9 @@
                     Slog.e(TAG, "Failed to stop model: " + ret);
                     return ret;
                 }
-                mIntentCallbacks.remove(soundModelId.getUuid());
+                synchronized (mCallbacksLock) {
+                    mIntentCallbacks.remove(soundModelId.getUuid());
+                }
             }
             return STATUS_OK;
         }
@@ -379,14 +393,14 @@
         public boolean isRecognitionActive(ParcelUuid parcelUuid) {
             enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
             if (!isInitialized()) return false;
-            synchronized (mLock) {
+            synchronized (mCallbacksLock) {
                 LocalSoundTriggerRecognitionStatusCallback callback =
                         mIntentCallbacks.get(parcelUuid.getUuid());
                 if (callback == null) {
                     return false;
                 }
-                return mSoundTriggerHelper.isRecognitionRequested(parcelUuid.getUuid());
             }
+            return mSoundTriggerHelper.isRecognitionRequested(parcelUuid.getUuid());
         }
     }
 
@@ -513,7 +527,7 @@
 
         private void removeCallback(boolean releaseWakeLock) {
             mCallbackIntent = null;
-            synchronized (mLock) {
+            synchronized (mCallbacksLock) {
                 mIntentCallbacks.remove(mUuid);
                 if (releaseWakeLock) {
                     mWakelock.release();
@@ -523,7 +537,7 @@
     }
 
     private void grabWakeLock() {
-        synchronized (mLock) {
+        synchronized (mCallbacksLock) {
             if (mWakelock == null) {
                 PowerManager pm = ((PowerManager) mContext.getSystemService(Context.POWER_SERVICE));
                 mWakelock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
@@ -537,7 +551,7 @@
         public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode,
                 String resultData, Bundle resultExtras) {
             // We're only ever invoked when the callback is done, so release the lock.
-            synchronized (mLock) {
+            synchronized (mCallbacksLock) {
                 mWakelock.release();
             }
         }
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index c3a2ceb..56e1e64 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -280,6 +280,36 @@
      * {@hide}
      */
     public static final int NORMAL_UNSPECIFIED = 65;
+
+    /**
+     * Stk Call Control modified DIAL request to video DIAL request.
+     * {@hide}
+     */
+    public static final int DIAL_MODIFIED_TO_DIAL_VIDEO = 66;
+
+    /**
+     * Stk Call Control modified Video DIAL request to SS request.
+     * {@hide}
+     */
+    public static final int DIAL_VIDEO_MODIFIED_TO_SS = 67;
+
+    /**
+     * Stk Call Control modified Video DIAL request to USSD request.
+     * {@hide}
+     */
+    public static final int DIAL_VIDEO_MODIFIED_TO_USSD = 68;
+
+    /**
+     * Stk Call Control modified Video DIAL request to DIAL request.
+     * {@hide}
+     */
+    public static final int DIAL_VIDEO_MODIFIED_TO_DIAL = 69;
+
+    /**
+     * Stk Call Control modified Video DIAL request to Video DIAL request.
+     * {@hide}
+     */
+    public static final int DIAL_VIDEO_MODIFIED_TO_DIAL_VIDEO = 70;
     //*********************************************************************************************
     // When adding a disconnect type:
     // 1) Update toString() with the newly added disconnect type.
@@ -382,6 +412,16 @@
             return "DIAL_MODIFIED_TO_SS";
         case DIAL_MODIFIED_TO_DIAL:
             return "DIAL_MODIFIED_TO_DIAL";
+        case DIAL_MODIFIED_TO_DIAL_VIDEO:
+            return "DIAL_MODIFIED_TO_DIAL_VIDEO";
+        case DIAL_VIDEO_MODIFIED_TO_SS:
+            return "DIAL_VIDEO_MODIFIED_TO_SS";
+        case DIAL_VIDEO_MODIFIED_TO_USSD:
+            return "DIAL_VIDEO_MODIFIED_TO_USSD";
+        case DIAL_VIDEO_MODIFIED_TO_DIAL:
+            return "DIAL_VIDEO_MODIFIED_TO_DIAL";
+        case DIAL_VIDEO_MODIFIED_TO_DIAL_VIDEO:
+            return "DIAL_VIDEO_MODIFIED_TO_DIAL_VIDEO";
         case ERROR_UNSPECIFIED:
             return "ERROR_UNSPECIFIED";
         case OUTGOING_FAILURE:
diff --git a/telephony/java/android/telephony/ims/stub/ImsUtListenerImplBase.java b/telephony/java/android/telephony/ims/stub/ImsUtListenerImplBase.java
index b371efb..daa74c8 100644
--- a/telephony/java/android/telephony/ims/stub/ImsUtListenerImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsUtListenerImplBase.java
@@ -21,6 +21,7 @@
 
 import com.android.ims.ImsCallForwardInfo;
 import com.android.ims.ImsReasonInfo;
+import com.android.ims.ImsSsData;
 import com.android.ims.ImsSsInfo;
 import com.android.ims.internal.IImsUt;
 import com.android.ims.internal.IImsUtListener;
@@ -85,4 +86,10 @@
     public void utConfigurationCallWaitingQueried(IImsUt ut, int id, ImsSsInfo[] cwInfo)
             throws RemoteException {
     }
+
+    /**
+     * Notifies client when Supplementary Service indication is received
+     */
+    @Override
+    public void onSupplementaryServiceIndication(ImsSsData ssData) {}
 }
diff --git a/telephony/java/com/android/ims/ImsReasonInfo.java b/telephony/java/com/android/ims/ImsReasonInfo.java
index cdfc1fd..6ad54c1 100644
--- a/telephony/java/com/android/ims/ImsReasonInfo.java
+++ b/telephony/java/com/android/ims/ImsReasonInfo.java
@@ -111,6 +111,16 @@
     // and this capability is not supported by the network.
     public static final int CODE_IMEI_NOT_ACCEPTED = 243;
 
+    //STK CC errors
+    public static final int CODE_DIAL_MODIFIED_TO_USSD = 244;
+    public static final int CODE_DIAL_MODIFIED_TO_SS = 245;
+    public static final int CODE_DIAL_MODIFIED_TO_DIAL = 246;
+    public static final int CODE_DIAL_MODIFIED_TO_DIAL_VIDEO = 247;
+    public static final int CODE_DIAL_VIDEO_MODIFIED_TO_DIAL = 248;
+    public static final int CODE_DIAL_VIDEO_MODIFIED_TO_DIAL_VIDEO = 249;
+    public static final int CODE_DIAL_VIDEO_MODIFIED_TO_SS = 250;
+    public static final int CODE_DIAL_VIDEO_MODIFIED_TO_USSD = 251;
+
     /**
      * STATUSCODE (SIP response code) (IMS -> Telephony)
      */
@@ -217,6 +227,11 @@
     public static final int CODE_UT_OPERATION_NOT_ALLOWED = 803;
     public static final int CODE_UT_NETWORK_ERROR = 804;
     public static final int CODE_UT_CB_PASSWORD_MISMATCH = 821;
+    //STK CC errors
+    public static final int CODE_UT_SS_MODIFIED_TO_DIAL = 822;
+    public static final int CODE_UT_SS_MODIFIED_TO_USSD = 823;
+    public static final int CODE_UT_SS_MODIFIED_TO_SS = 824;
+    public static final int CODE_UT_SS_MODIFIED_TO_DIAL_VIDEO = 825;
 
     /**
      * ECBM
diff --git a/telephony/java/com/android/ims/ImsSsData.aidl b/telephony/java/com/android/ims/ImsSsData.aidl
new file mode 100644
index 0000000..33f8306
--- /dev/null
+++ b/telephony/java/com/android/ims/ImsSsData.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ims;
+
+parcelable ImsSsData;
diff --git a/telephony/java/com/android/ims/ImsSsData.java b/telephony/java/com/android/ims/ImsSsData.java
new file mode 100644
index 0000000..7336c13
--- /dev/null
+++ b/telephony/java/com/android/ims/ImsSsData.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.ims;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+
+/**
+ * Provided STK Call Control Suplementary Service information
+ *
+ * {@hide}
+ */
+public class ImsSsData implements Parcelable {
+
+    //ServiceType
+    public static final int SS_CFU = 0;
+    public static final int SS_CF_BUSY = 1;
+    public static final int SS_CF_NO_REPLY = 2;
+    public static final int SS_CF_NOT_REACHABLE = 3;
+    public static final int SS_CF_ALL = 4;
+    public static final int SS_CF_ALL_CONDITIONAL = 5;
+    public static final int SS_CFUT = 6;
+    public static final int SS_CLIP = 7;
+    public static final int SS_CLIR = 8;
+    public static final int SS_COLP = 9;
+    public static final int SS_COLR = 10;
+    public static final int SS_CNAP = 11;
+    public static final int SS_WAIT = 12;
+    public static final int SS_BAOC = 13;
+    public static final int SS_BAOIC = 14;
+    public static final int SS_BAOIC_EXC_HOME = 15;
+    public static final int SS_BAIC = 16;
+    public static final int SS_BAIC_ROAMING = 17;
+    public static final int SS_ALL_BARRING = 18;
+    public static final int SS_OUTGOING_BARRING = 19;
+    public static final int SS_INCOMING_BARRING = 20;
+    public static final int SS_INCOMING_BARRING_DN = 21;
+    public static final int SS_INCOMING_BARRING_ANONYMOUS = 22;
+
+    //SSRequestType
+    public static final int SS_ACTIVATION = 0;
+    public static final int SS_DEACTIVATION = 1;
+    public static final int SS_INTERROGATION = 2;
+    public static final int SS_REGISTRATION = 3;
+    public static final int SS_ERASURE = 4;
+
+    //TeleserviceType
+    public static final int SS_ALL_TELE_AND_BEARER_SERVICES = 0;
+    public static final int SS_ALL_TELESEVICES = 1;
+    public static final int SS_TELEPHONY = 2;
+    public static final int SS_ALL_DATA_TELESERVICES = 3;
+    public static final int SS_SMS_SERVICES = 4;
+    public static final int SS_ALL_TELESERVICES_EXCEPT_SMS = 5;
+
+    // Refer to ServiceType
+    public int serviceType;
+    // Refere to SSRequestType
+    public int requestType;
+    // Refer to TeleserviceType
+    public int teleserviceType;
+    // Service Class
+    public int serviceClass;
+    // Error information
+    public int result;
+
+    public int[] ssInfo; /* Valid for all supplementary services.
+                             This field will be empty for RequestType SS_INTERROGATION
+                             and ServiceType SS_CF_*, SS_INCOMING_BARRING_DN,
+                             SS_INCOMING_BARRING_ANONYMOUS.*/
+
+    public ImsCallForwardInfo[] cfInfo; /* Valid only for supplementary services
+                                            ServiceType SS_CF_* and RequestType SS_INTERROGATION */
+
+    public ImsSsInfo[] imsSsInfo;   /* Valid only for ServiceType SS_INCOMING_BARRING_DN and
+                                        ServiceType SS_INCOMING_BARRING_ANONYMOUS */
+
+    public ImsSsData() {}
+
+    public ImsSsData(Parcel in) {
+        readFromParcel(in);
+    }
+
+    public static final Creator<ImsSsData> CREATOR = new Creator<ImsSsData>() {
+        @Override
+        public ImsSsData createFromParcel(Parcel in) {
+            return new ImsSsData(in);
+        }
+
+        @Override
+        public ImsSsData[] newArray(int size) {
+            return new ImsSsData[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(serviceType);
+        out.writeInt(requestType);
+        out.writeInt(teleserviceType);
+        out.writeInt(serviceClass);
+        out.writeInt(result);
+        out.writeIntArray(ssInfo);
+        out.writeParcelableArray(cfInfo, 0);
+    }
+
+    private void readFromParcel(Parcel in) {
+        serviceType = in.readInt();
+        requestType = in.readInt();
+        teleserviceType = in.readInt();
+        serviceClass = in.readInt();
+        result = in.readInt();
+        ssInfo = in.createIntArray();
+        cfInfo = (ImsCallForwardInfo[])in.readParcelableArray(this.getClass().getClassLoader());
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    public boolean isTypeCF() {
+        return (serviceType == SS_CFU || serviceType == SS_CF_BUSY ||
+              serviceType == SS_CF_NO_REPLY || serviceType == SS_CF_NOT_REACHABLE ||
+              serviceType == SS_CF_ALL || serviceType == SS_CF_ALL_CONDITIONAL);
+    }
+
+    public boolean isTypeUnConditional() {
+        return (serviceType == SS_CFU || serviceType == SS_CF_ALL);
+    }
+
+    public boolean isTypeCW() {
+        return (serviceType == SS_WAIT);
+    }
+
+    public boolean isTypeClip() {
+        return (serviceType == SS_CLIP);
+    }
+
+    public boolean isTypeColr() {
+        return (serviceType == SS_COLR);
+    }
+
+    public boolean isTypeColp() {
+        return (serviceType == SS_COLP);
+    }
+
+    public boolean isTypeClir() {
+        return (serviceType == SS_CLIR);
+    }
+
+    public boolean isTypeIcb() {
+        return (serviceType == SS_INCOMING_BARRING_DN ||
+                serviceType == SS_INCOMING_BARRING_ANONYMOUS);
+    }
+
+    public boolean isTypeBarring() {
+        return (serviceType == SS_BAOC || serviceType == SS_BAOIC ||
+              serviceType == SS_BAOIC_EXC_HOME || serviceType == SS_BAIC ||
+              serviceType == SS_BAIC_ROAMING || serviceType == SS_ALL_BARRING ||
+              serviceType == SS_OUTGOING_BARRING || serviceType == SS_INCOMING_BARRING);
+    }
+
+    public boolean isTypeInterrogation() {
+        return (requestType == SS_INTERROGATION);
+    }
+
+    public String toString() {
+        return "[ImsSsData] " + "ServiceType: " + serviceType
+            + " RequestType: " + requestType
+            + " TeleserviceType: " + teleserviceType
+            + " ServiceClass: " + serviceClass
+            + " Result: " + result;
+    }
+}
diff --git a/telephony/java/com/android/ims/ImsUtInterface.java b/telephony/java/com/android/ims/ImsUtInterface.java
index 250371f..14c184a 100644
--- a/telephony/java/com/android/ims/ImsUtInterface.java
+++ b/telephony/java/com/android/ims/ImsUtInterface.java
@@ -16,6 +16,7 @@
 
 package com.android.ims;
 
+import android.os.Handler;
 import android.os.Message;
 
 /**
@@ -188,4 +189,18 @@
      * Updates the configuration of the COLP supplementary service.
      */
     public void updateCOLP(boolean enable, Message result);
+
+    /**
+     * Register for UNSOL_ON_SS indications.
+     * @param handler the {@link Handler} that is notified when there is an ss indication.
+     * @param event  Supplimentary service indication event.
+     * @param Object user object.
+     */
+    public void registerForSuppServiceIndication(Handler handler, int event, Object object);
+
+    /**
+     * Deregister for UNSOL_ON_SS indications.
+     * @param handler the {@link Handler} that is notified when there is an ss indication.
+     */
+    public void unregisterForSuppServiceIndication(Handler handler);
 }
diff --git a/telephony/java/com/android/ims/internal/IImsUtListener.aidl b/telephony/java/com/android/ims/internal/IImsUtListener.aidl
index 300273a..1bc0369 100644
--- a/telephony/java/com/android/ims/internal/IImsUtListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsUtListener.aidl
@@ -19,6 +19,7 @@
 import android.os.Bundle;
 
 import com.android.ims.ImsCallForwardInfo;
+import com.android.ims.ImsSsData;
 import com.android.ims.ImsSsInfo;
 import com.android.ims.internal.IImsUt;
 import com.android.ims.ImsReasonInfo;
@@ -56,4 +57,11 @@
      */
     void utConfigurationCallWaitingQueried(in IImsUt ut,
             int id, in ImsSsInfo[] cwInfo);
+
+    /**
+     * Notifies client when Supplementary Service indication is received
+     *
+     * @param ssData Details of SS request and response information
+     */
+    void onSupplementaryServiceIndication(in ImsSsData ssData);
 }
diff --git a/tests/net/java/android/net/ip/IpManagerTest.java b/tests/net/java/android/net/ip/IpManagerTest.java
index 22d88fb..ebf121a 100644
--- a/tests/net/java/android/net/ip/IpManagerTest.java
+++ b/tests/net/java/android/net/ip/IpManagerTest.java
@@ -69,6 +69,8 @@
 
 /**
  * Tests for IpManager.
+ *
+ * TODO: Rename to IpClientTest.
  */
 @RunWith(AndroidJUnit4.class)
 @SmallTest
@@ -111,6 +113,10 @@
         verify(mNMService, times(1)).registerObserver(arg.capture());
         mObserver = arg.getValue();
         reset(mNMService);
+        final LinkProperties emptyLp = new LinkProperties();
+        emptyLp.setInterfaceName(ifname);
+        verify(mCb, timeout(100)).onLinkPropertiesChange(eq(emptyLp));
+        reset(mCb);
         return ipm;
     }