Merge "AID: Change loop to repeat and set from xml"
diff --git a/api/current.txt b/api/current.txt
index ab6f13b..7bdff3f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7445,6 +7445,7 @@
     method public java.util.Map<java.lang.String, android.app.usage.UsageStats> queryAndAggregateUsageStats(long, long);
     method public java.util.List<android.app.usage.ConfigurationStats> queryConfigurations(int, long, long);
     method public android.app.usage.UsageEvents queryEvents(long, long);
+    method public android.app.usage.UsageEvents queryEventsForSelf(long, long);
     method public java.util.List<android.app.usage.UsageStats> queryUsageStats(int, long, long);
     field public static final int INTERVAL_BEST = 4; // 0x4
     field public static final int INTERVAL_DAILY = 0; // 0x0
@@ -22865,12 +22866,12 @@
 
   public static class MediaBrowser2.BrowserCallback extends android.media.MediaController2.ControllerCallback {
     ctor public MediaBrowser2.BrowserCallback();
-    method public void onChildrenChanged(java.lang.String, int, android.os.Bundle);
-    method public void onGetChildrenDone(java.lang.String, int, int, java.util.List<android.media.MediaItem2>, android.os.Bundle);
-    method public void onGetItemDone(java.lang.String, android.media.MediaItem2);
-    method public void onGetLibraryRootDone(android.os.Bundle, java.lang.String, android.os.Bundle);
-    method public void onGetSearchResultDone(java.lang.String, int, int, java.util.List<android.media.MediaItem2>, android.os.Bundle);
-    method public void onSearchResultChanged(java.lang.String, int, android.os.Bundle);
+    method public void onChildrenChanged(android.media.MediaBrowser2, java.lang.String, int, android.os.Bundle);
+    method public void onGetChildrenDone(android.media.MediaBrowser2, java.lang.String, int, int, java.util.List<android.media.MediaItem2>, android.os.Bundle);
+    method public void onGetItemDone(android.media.MediaBrowser2, java.lang.String, android.media.MediaItem2);
+    method public void onGetLibraryRootDone(android.media.MediaBrowser2, android.os.Bundle, java.lang.String, android.os.Bundle);
+    method public void onGetSearchResultDone(android.media.MediaBrowser2, java.lang.String, int, int, java.util.List<android.media.MediaItem2>, android.os.Bundle);
+    method public void onSearchResultChanged(android.media.MediaBrowser2, java.lang.String, int, android.os.Bundle);
   }
 
   public final class MediaCas implements java.lang.AutoCloseable {
@@ -23392,20 +23393,20 @@
 
   public static abstract class MediaController2.ControllerCallback {
     ctor public MediaController2.ControllerCallback();
-    method public void onAllowedCommandsChanged(android.media.MediaSession2.CommandGroup);
-    method public void onBufferedPositionChanged(long);
-    method public void onConnected(android.media.MediaSession2.CommandGroup);
-    method public void onCurrentPlaylistItemChanged(android.media.MediaItem2);
-    method public void onCustomCommand(android.media.MediaSession2.Command, android.os.Bundle, android.os.ResultReceiver);
-    method public void onCustomLayoutChanged(java.util.List<android.media.MediaSession2.CommandButton>);
-    method public void onDisconnected();
-    method public void onError(int, android.os.Bundle);
-    method public void onPlaybackInfoChanged(android.media.MediaController2.PlaybackInfo);
-    method public void onPlaybackSpeedChanged(float);
-    method public void onPlayerStateChanged(int);
-    method public void onPlaylistChanged(java.util.List<android.media.MediaItem2>);
-    method public void onPlaylistParamsChanged(android.media.MediaSession2.PlaylistParams);
-    method public void onPositionChanged(long, long);
+    method public void onAllowedCommandsChanged(android.media.MediaController2, android.media.MediaSession2.CommandGroup);
+    method public void onBufferedPositionChanged(android.media.MediaController2, long);
+    method public void onConnected(android.media.MediaController2, android.media.MediaSession2.CommandGroup);
+    method public void onCurrentPlaylistItemChanged(android.media.MediaController2, android.media.MediaItem2);
+    method public void onCustomCommand(android.media.MediaController2, android.media.MediaSession2.Command, android.os.Bundle, android.os.ResultReceiver);
+    method public void onCustomLayoutChanged(android.media.MediaController2, java.util.List<android.media.MediaSession2.CommandButton>);
+    method public void onDisconnected(android.media.MediaController2);
+    method public void onError(android.media.MediaController2, int, android.os.Bundle);
+    method public void onPlaybackInfoChanged(android.media.MediaController2, android.media.MediaController2.PlaybackInfo);
+    method public void onPlaybackSpeedChanged(android.media.MediaController2, float);
+    method public void onPlayerStateChanged(android.media.MediaController2, int);
+    method public void onPlaylistChanged(android.media.MediaController2, java.util.List<android.media.MediaItem2>);
+    method public void onPlaylistParamsChanged(android.media.MediaController2, android.media.MediaSession2.PlaylistParams);
+    method public void onPositionChanged(android.media.MediaController2, long, long);
   }
 
   public static final class MediaController2.PlaybackInfo {
@@ -23874,13 +23875,13 @@
 
   public static class MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback extends android.media.MediaSession2.SessionCallback {
     ctor public MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback(android.content.Context);
-    method public java.util.List<android.media.MediaItem2> onGetChildren(android.media.MediaSession2.ControllerInfo, java.lang.String, int, int, android.os.Bundle);
-    method public android.media.MediaItem2 onGetItem(android.media.MediaSession2.ControllerInfo, java.lang.String);
-    method public android.media.MediaLibraryService2.LibraryRoot onGetLibraryRoot(android.media.MediaSession2.ControllerInfo, android.os.Bundle);
-    method public java.util.List<android.media.MediaItem2> onGetSearchResult(android.media.MediaSession2.ControllerInfo, java.lang.String, int, int, android.os.Bundle);
-    method public void onSearch(android.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle);
-    method public void onSubscribe(android.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle);
-    method public void onUnsubscribe(android.media.MediaSession2.ControllerInfo, java.lang.String);
+    method public java.util.List<android.media.MediaItem2> onGetChildren(android.media.MediaLibraryService2.MediaLibrarySession, android.media.MediaSession2.ControllerInfo, java.lang.String, int, int, android.os.Bundle);
+    method public android.media.MediaItem2 onGetItem(android.media.MediaLibraryService2.MediaLibrarySession, android.media.MediaSession2.ControllerInfo, java.lang.String);
+    method public android.media.MediaLibraryService2.LibraryRoot onGetLibraryRoot(android.media.MediaLibraryService2.MediaLibrarySession, android.media.MediaSession2.ControllerInfo, android.os.Bundle);
+    method public java.util.List<android.media.MediaItem2> onGetSearchResult(android.media.MediaLibraryService2.MediaLibrarySession, android.media.MediaSession2.ControllerInfo, java.lang.String, int, int, android.os.Bundle);
+    method public void onSearch(android.media.MediaLibraryService2.MediaLibrarySession, android.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle);
+    method public void onSubscribe(android.media.MediaLibraryService2.MediaLibrarySession, android.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle);
+    method public void onUnsubscribe(android.media.MediaLibraryService2.MediaLibrarySession, android.media.MediaSession2.ControllerInfo, java.lang.String);
   }
 
   public final class MediaMetadata implements android.os.Parcelable {
@@ -24346,7 +24347,6 @@
     method public abstract void prepareDrm(java.util.UUID) throws android.media.MediaPlayer2.ProvisioningNetworkErrorException, android.media.MediaPlayer2.ProvisioningServerErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
     method public abstract byte[] provideDrmKeyResponse(byte[], byte[]) throws android.media.DeniedByServerException, android.media.MediaPlayer2.NoDrmSchemeException;
     method public abstract void releaseDrm() throws android.media.MediaPlayer2.NoDrmSchemeException;
-    method public abstract void reset();
     method public abstract void restoreDrmKeys(byte[]) throws android.media.MediaPlayer2.NoDrmSchemeException;
     method public void seekTo(long);
     method public abstract void seekTo(long, int);
@@ -24511,6 +24511,7 @@
     method public abstract void play();
     method public abstract void prepare();
     method public abstract void registerPlayerEventCallback(java.util.concurrent.Executor, android.media.MediaPlayerBase.PlayerEventCallback);
+    method public abstract void reset();
     method public abstract void seekTo(long);
     method public abstract void setAudioAttributes(android.media.AudioAttributes);
     method public abstract void setDataSource(android.media.DataSourceDesc);
@@ -24968,17 +24969,17 @@
 
   public static abstract class MediaSession2.SessionCallback {
     ctor public MediaSession2.SessionCallback(android.content.Context);
-    method public boolean onCommandRequest(android.media.MediaSession2.ControllerInfo, android.media.MediaSession2.Command);
-    method public android.media.MediaSession2.CommandGroup onConnect(android.media.MediaSession2.ControllerInfo);
-    method public void onCustomCommand(android.media.MediaSession2.ControllerInfo, android.media.MediaSession2.Command, android.os.Bundle, android.os.ResultReceiver);
-    method public void onDisconnected(android.media.MediaSession2.ControllerInfo);
-    method public void onPlayFromMediaId(android.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle);
-    method public void onPlayFromSearch(android.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle);
-    method public void onPlayFromUri(android.media.MediaSession2.ControllerInfo, android.net.Uri, android.os.Bundle);
-    method public void onPrepareFromMediaId(android.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle);
-    method public void onPrepareFromSearch(android.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle);
-    method public void onPrepareFromUri(android.media.MediaSession2.ControllerInfo, android.net.Uri, android.os.Bundle);
-    method public void onSetRating(android.media.MediaSession2.ControllerInfo, java.lang.String, android.media.Rating2);
+    method public boolean onCommandRequest(android.media.MediaSession2, android.media.MediaSession2.ControllerInfo, android.media.MediaSession2.Command);
+    method public android.media.MediaSession2.CommandGroup onConnect(android.media.MediaSession2, android.media.MediaSession2.ControllerInfo);
+    method public void onCustomCommand(android.media.MediaSession2, android.media.MediaSession2.ControllerInfo, android.media.MediaSession2.Command, android.os.Bundle, android.os.ResultReceiver);
+    method public void onDisconnected(android.media.MediaSession2, android.media.MediaSession2.ControllerInfo);
+    method public void onPlayFromMediaId(android.media.MediaSession2, android.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle);
+    method public void onPlayFromSearch(android.media.MediaSession2, android.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle);
+    method public void onPlayFromUri(android.media.MediaSession2, android.media.MediaSession2.ControllerInfo, android.net.Uri, android.os.Bundle);
+    method public void onPrepareFromMediaId(android.media.MediaSession2, android.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle);
+    method public void onPrepareFromSearch(android.media.MediaSession2, android.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle);
+    method public void onPrepareFromUri(android.media.MediaSession2, android.media.MediaSession2.ControllerInfo, android.net.Uri, android.os.Bundle);
+    method public void onSetRating(android.media.MediaSession2, android.media.MediaSession2.ControllerInfo, java.lang.String, android.media.Rating2);
   }
 
   public abstract class MediaSessionService2 extends android.app.Service {
@@ -42233,6 +42234,8 @@
     field public static final java.lang.String KEY_CARRIER_INSTANT_LETTERING_ESCAPED_CHARS_STRING = "carrier_instant_lettering_escaped_chars_string";
     field public static final java.lang.String KEY_CARRIER_INSTANT_LETTERING_INVALID_CHARS_STRING = "carrier_instant_lettering_invalid_chars_string";
     field public static final java.lang.String KEY_CARRIER_INSTANT_LETTERING_LENGTH_LIMIT_INT = "carrier_instant_lettering_length_limit_int";
+    field public static final java.lang.String KEY_CARRIER_NAME_OVERRIDE_BOOL = "carrier_name_override_bool";
+    field public static final java.lang.String KEY_CARRIER_NAME_STRING = "carrier_name_string";
     field public static final java.lang.String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool";
     field public static final java.lang.String KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL = "carrier_use_ims_first_for_emergency_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_AVAILABLE_BOOL = "carrier_volte_available_bool";
@@ -42381,9 +42384,9 @@
     method public int getCid();
     method public int getLac();
     method public deprecated int getMcc();
-    method public java.lang.String getMccStr();
+    method public java.lang.String getMccString();
     method public deprecated int getMnc();
-    method public java.lang.String getMncStr();
+    method public java.lang.String getMncString();
     method public java.lang.String getMobileNetworkOperator();
     method public java.lang.CharSequence getOperatorAlphaLong();
     method public java.lang.CharSequence getOperatorAlphaShort();
@@ -42397,9 +42400,9 @@
     method public int getCi();
     method public int getEarfcn();
     method public deprecated int getMcc();
-    method public java.lang.String getMccStr();
+    method public java.lang.String getMccString();
     method public deprecated int getMnc();
-    method public java.lang.String getMncStr();
+    method public java.lang.String getMncString();
     method public java.lang.String getMobileNetworkOperator();
     method public java.lang.CharSequence getOperatorAlphaLong();
     method public java.lang.CharSequence getOperatorAlphaShort();
@@ -42413,8 +42416,8 @@
     method public int getCid();
     method public int getCpid();
     method public int getLac();
-    method public java.lang.String getMccStr();
-    method public java.lang.String getMncStr();
+    method public java.lang.String getMccString();
+    method public java.lang.String getMncString();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.telephony.CellIdentityTdscdma> CREATOR;
   }
@@ -42423,9 +42426,9 @@
     method public int getCid();
     method public int getLac();
     method public deprecated int getMcc();
-    method public java.lang.String getMccStr();
+    method public java.lang.String getMccString();
     method public deprecated int getMnc();
-    method public java.lang.String getMncStr();
+    method public java.lang.String getMncString();
     method public java.lang.String getMobileNetworkOperator();
     method public java.lang.CharSequence getOperatorAlphaLong();
     method public java.lang.CharSequence getOperatorAlphaShort();
@@ -50778,7 +50781,6 @@
     method public abstract boolean performEditorAction(int);
     method public abstract boolean performPrivateCommand(java.lang.String, android.os.Bundle);
     method public abstract boolean reportFullscreenMode(boolean);
-    method public default void reportLanguageHint(android.os.LocaleList);
     method public abstract boolean requestCursorUpdates(int);
     method public abstract boolean sendKeyEvent(android.view.KeyEvent);
     method public abstract boolean setComposingRegion(int, int);
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 9b58a14..e98b54d 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -330,9 +330,7 @@
     mLastByteSizeTimes[key] = timestampNs;
     if (totalBytes >
         StatsdStats::kMaxMetricsBytesPerConfig) {  // Too late. We need to start clearing data.
-        // TODO(b/70571383): By 12/15/2017 add API to drop data directly
-        ProtoOutputStream proto;
-        metricsManager.onDumpReport(timestampNs, &proto);
+        metricsManager.dropData(timestampNs);
         StatsdStats::getInstance().noteDataDropped(key);
         VLOG("StatsD had to toss out metrics for %s", key.ToString().c_str());
     } else if (totalBytes > .9 * StatsdStats::kMaxMetricsBytesPerConfig) {
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 7a6aa1e..a672ab4 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -113,7 +113,6 @@
     FRIEND_TEST(StatsLogProcessorTest, TestRateLimitByteSize);
     FRIEND_TEST(StatsLogProcessorTest, TestRateLimitBroadcast);
     FRIEND_TEST(StatsLogProcessorTest, TestDropWhenByteSizeTooLarge);
-    FRIEND_TEST(StatsLogProcessorTest, TestDropWhenByteSizeTooLarge);
     FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration1);
     FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration2);
     FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration3);
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index af2e362..671c57f 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -151,8 +151,11 @@
     protoOutput->end(protoToken);
 
     mPastBuckets.clear();
+}
 
-    // TODO: Clear mDimensionKeyMap once the report is dumped.
+void CountMetricProducer::dropDataLocked(const uint64_t dropTimeNs) {
+    flushIfNeededLocked(dropTimeNs);
+    mPastBuckets.clear();
 }
 
 void CountMetricProducer::onConditionChangedLocked(const bool conditionMet,
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h
index 0c4291d..1d8e42b 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.h
+++ b/cmds/statsd/src/metrics/CountMetricProducer.h
@@ -69,6 +69,8 @@
 
     void dumpStatesLocked(FILE* out, bool verbose) const override{};
 
+    void dropDataLocked(const uint64_t dropTimeNs) override;
+
     // Util function to flush the old packet.
     void flushIfNeededLocked(const uint64_t& newEventTime) override;
 
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index 80329c3..ac39662 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -221,6 +221,11 @@
     }
 }
 
+void DurationMetricProducer::dropDataLocked(const uint64_t dropTimeNs) {
+    flushIfNeededLocked(dropTimeNs);
+    mPastBuckets.clear();
+}
+
 void DurationMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
                                                 ProtoOutputStream* protoOutput) {
     flushIfNeededLocked(dumpTimeNs);
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index 73d074f..23408a7 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -74,6 +74,8 @@
 
     void dumpStatesLocked(FILE* out, bool verbose) const override;
 
+    void dropDataLocked(const uint64_t dropTimeNs) override;
+
     // Util function to flush the old packet.
     void flushIfNeededLocked(const uint64_t& eventTime);
 
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp
index 96d0cfc..fff91f6 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp
@@ -75,6 +75,10 @@
     VLOG("~EventMetricProducer() called");
 }
 
+void EventMetricProducer::dropDataLocked(const uint64_t dropTimeNs) {
+    mProto->clear();
+}
+
 void EventMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventTime) {
 }
 
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.h b/cmds/statsd/src/metrics/EventMetricProducer.h
index 3f2c5a5..d6f81fd 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.h
+++ b/cmds/statsd/src/metrics/EventMetricProducer.h
@@ -55,6 +55,8 @@
     // Internal interface to handle sliced condition change.
     void onSlicedConditionMayChangeLocked(const uint64_t eventTime) override;
 
+    void dropDataLocked(const uint64_t dropTimeNs) override;
+
     // Internal function to calculate the current used bytes.
     size_t byteSizeLocked() const override;
 
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 7d09ff9..000c7a7 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -353,6 +353,11 @@
     }
 }
 
+void GaugeMetricProducer::dropDataLocked(const uint64_t dropTimeNs) {
+    flushIfNeededLocked(dropTimeNs);
+    mPastBuckets.clear();
+}
+
 // When a new matched event comes in, we check if event falls into the current
 // bucket. If not, flush the old counter to past buckets and initialize the new
 // bucket.
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index c3ae6ce..ca8dc75 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -108,6 +108,8 @@
 
     void dumpStatesLocked(FILE* out, bool verbose) const override{};
 
+    void dropDataLocked(const uint64_t dropTimeNs) override;
+
     // Util function to flush the old packet.
     void flushIfNeededLocked(const uint64_t& eventTime) override;
 
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index 2bf6241..05b7f87 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -148,6 +148,15 @@
         return mMetricId;
     }
 
+    // Let MetricProducer drop in-memory data to save memory.
+    // We still need to keep future data valid and anomaly tracking work, which means we will
+    // have to flush old data, informing anomaly trackers then safely drop old data.
+    // We still keep current bucket data for future metrics' validity.
+    void dropData(const uint64_t dropTimeNs) {
+        std::lock_guard<std::mutex> lock(mMutex);
+        dropDataLocked(dropTimeNs);
+    }
+
 protected:
     virtual void onConditionChangedLocked(const bool condition, const uint64_t eventTime) = 0;
     virtual void onSlicedConditionMayChangeLocked(const uint64_t eventTime) = 0;
@@ -179,6 +188,8 @@
         return mStartTimeNs + (mCurrentBucketNum + 1) * mBucketSizeNs;
     }
 
+    virtual void dropDataLocked(const uint64_t dropTimeNs) = 0;
+
     const int64_t mMetricId;
 
     const ConfigKey mConfigKey;
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index 4c8a7d8..0693031 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -173,6 +173,12 @@
     }
 }
 
+void MetricsManager::dropData(const uint64_t dropTimeNs) {
+    for (const auto& producer : mAllMetricProducers) {
+        producer->dropData(dropTimeNs);
+    }
+}
+
 void MetricsManager::onDumpReport(const uint64_t dumpTimeStampNs, ProtoOutputStream* protoOutput) {
     VLOG("=========================Metric Reports Start==========================");
     // one StatsLogReport per MetricProduer
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index b50ef4a..a32e037 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -73,6 +73,8 @@
         return mLastReportTimeNs;
     };
 
+    virtual void dropData(const uint64_t dropTimeNs);
+
     // Config source owner can call onDumpReport() to get all the metrics collected.
     virtual void onDumpReport(const uint64_t dumpTimeNs,
                               android::util::ProtoOutputStream* protoOutput);
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index 35fcdc4..f6bba3d 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -129,6 +129,11 @@
     VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
 }
 
+void ValueMetricProducer::dropDataLocked(const uint64_t dropTimeNs) {
+    flushIfNeededLocked(dropTimeNs);
+    mPastBuckets.clear();
+}
+
 void ValueMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
                                              ProtoOutputStream* protoOutput) {
     VLOG("metric %lld dump report now...", (long long)mMetricId);
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index b518f2f..5e42bd2 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -106,6 +106,8 @@
 
     void flushCurrentBucketLocked(const uint64_t& eventTimeNs) override;
 
+    void dropDataLocked(const uint64_t dropTimeNs) override;
+
     const FieldMatcher mValueField;
 
     std::shared_ptr<StatsPullerManager> mStatsPullerManager;
diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp
index 3238b74..efed42e 100644
--- a/cmds/statsd/tests/StatsLogProcessor_test.cpp
+++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp
@@ -51,7 +51,8 @@
     }
 
     MOCK_METHOD0(byteSize, size_t());
-    MOCK_METHOD2(onDumpReport, void(const uint64_t timeNs, ProtoOutputStream* output));
+
+    MOCK_METHOD1(dropData, void(const uint64_t dropTimeNs));
 };
 
 TEST(StatsLogProcessorTest, TestRateLimitByteSize) {
@@ -114,7 +115,7 @@
             .Times(1)
             .WillRepeatedly(Return(int(StatsdStats::kMaxMetricsBytesPerConfig * 1.2)));
 
-    EXPECT_CALL(mockMetricsManager, onDumpReport(_, _)).Times(1);
+    EXPECT_CALL(mockMetricsManager, dropData(_)).Times(1);
 
     // Expect to call the onDumpReport and skip the broadcast.
     p.flushIfNecessaryLocked(1, key, mockMetricsManager);
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 2c400e0..fb4d3b8 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -526,41 +526,22 @@
 Landroid/content/res/AssetFileDescriptor;->mStartOffset:J
 Landroid/content/res/AssetManager;->addAssetPathAsSharedLibrary(Ljava/lang/String;)I
 Landroid/content/res/AssetManager;->addAssetPath(Ljava/lang/String;)I
-Landroid/content/res/AssetManager;->addAssetPathNative(Ljava/lang/String;Z)I
-Landroid/content/res/AssetManager;->addAssetPaths([Ljava/lang/String;)[I
-Landroid/content/res/AssetManager;->applyStyle(JIIJ[IIJJ)V
-Landroid/content/res/AssetManager;->ensureStringBlocks()[Landroid/content/res/StringBlock;
-Landroid/content/res/AssetManager;->getArraySize(I)I
 Landroid/content/res/AssetManager;->getAssignedPackageIdentifiers()Landroid/util/SparseArray;
-Landroid/content/res/AssetManager;->getCookieName(I)Ljava/lang/String;
-Landroid/content/res/AssetManager;->getNativeStringBlock(I)J
 Landroid/content/res/AssetManager;->getResourceBagText(II)Ljava/lang/CharSequence;
 Landroid/content/res/AssetManager;->getResourceEntryName(I)Ljava/lang/String;
 Landroid/content/res/AssetManager;->getResourceIdentifier(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I
 Landroid/content/res/AssetManager;->getResourceName(I)Ljava/lang/String;
 Landroid/content/res/AssetManager;->getResourcePackageName(I)Ljava/lang/String;
 Landroid/content/res/AssetManager;->getResourceTypeName(I)Ljava/lang/String;
-Landroid/content/res/AssetManager;->getStringBlockCount()I
 Landroid/content/res/AssetManager;-><init>()V
 Landroid/content/res/AssetManager;->isUpToDate()Z
-Landroid/content/res/AssetManager;->loadResourceBagValue(IILandroid/util/TypedValue;Z)I
-Landroid/content/res/AssetManager;->loadResourceValue(ISLandroid/util/TypedValue;Z)I
-Landroid/content/res/AssetManager;->loadThemeAttributeValue(JILandroid/util/TypedValue;Z)I
 Landroid/content/res/AssetManager;->mObject:J
-Landroid/content/res/AssetManager;->mStringBlocks:[Landroid/content/res/StringBlock;
-Landroid/content/res/AssetManager;->openNonAssetFdNative(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;
 Landroid/content/res/AssetManager;->openNonAsset(ILjava/lang/String;I)Ljava/io/InputStream;
 Landroid/content/res/AssetManager;->openNonAsset(ILjava/lang/String;)Ljava/io/InputStream;
 Landroid/content/res/AssetManager;->openNonAsset(Ljava/lang/String;I)Ljava/io/InputStream;
 Landroid/content/res/AssetManager;->openNonAsset(Ljava/lang/String;)Ljava/io/InputStream;
-Landroid/content/res/AssetManager;->openNonAssetNative(ILjava/lang/String;I)J
-Landroid/content/res/AssetManager;->openXmlAssetNative(ILjava/lang/String;)J
 Landroid/content/res/AssetManager;->resolveAttrs(JII[I[I[I[I)Z
-Landroid/content/res/AssetManager;->retrieveArray(I[I)I
-Landroid/content/res/AssetManager;->retrieveAttributes(J[I[I[I)Z
 Landroid/content/res/AssetManager;->setConfiguration(IILjava/lang/String;IIIIIIIIIIIIIII)V
-Landroid/content/res/AssetManager;->STYLE_NUM_ENTRIES:I
-Landroid/content/res/AssetManager;->STYLE_RESOURCE_ID:I
 Landroid/content/res/ColorStateList$ColorStateListFactory;-><init>(Landroid/content/res/ColorStateList;)V
 Landroid/content/res/ColorStateList;->mColors:[I
 Landroid/content/res/ColorStateList;->mDefaultColor:I
@@ -602,7 +583,6 @@
 Landroid/content/res/TypedArray;->mTheme:Landroid/content/res/Resources$Theme;
 Landroid/content/res/TypedArray;->mValue:Landroid/util/TypedValue;
 Landroid/content/res/TypedArray;->mXml:Landroid/content/res/XmlBlock$Parser;
-Landroid/content/res/XmlBlock;->close()V
 Landroid/content/res/XmlBlock;-><init>([B)V
 Landroid/content/res/XmlBlock;->newParser()Landroid/content/res/XmlResourceParser;
 Landroid/content/res/XmlBlock$Parser;->mParseState:J
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 3d04e2c..99c5d2b 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -6366,6 +6366,8 @@
         } else {
             writer.print(prefix); writer.println("No AutofillManager");
         }
+
+        ResourcesManager.getInstance().dump(prefix, writer);
     }
 
     /**
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index ea5932c..fc7d9a5 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -219,7 +219,7 @@
     }
 
     private AppComponentFactory createAppFactory(ApplicationInfo appInfo, ClassLoader cl) {
-        if (appInfo.appComponentFactory != null) {
+        if (appInfo.appComponentFactory != null && cl != null) {
             try {
                 return (AppComponentFactory) cl.loadClass(appInfo.appComponentFactory)
                         .newInstance();
@@ -613,6 +613,7 @@
             } else {
                 mClassLoader = ClassLoader.getSystemClassLoader();
             }
+            mAppComponentFactory = createAppFactory(mApplicationInfo, mClassLoader);
 
             return;
         }
@@ -687,6 +688,7 @@
                         librarySearchPath, libraryPermittedPath, mBaseClassLoader,
                         null /* classLoaderName */);
                 StrictMode.setThreadPolicy(oldPolicy);
+                mAppComponentFactory = createAppFactory(mApplicationInfo, mClassLoader);
             }
 
             return;
@@ -714,6 +716,7 @@
                     mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
                     libraryPermittedPath, mBaseClassLoader,
                     mApplicationInfo.classLoaderName);
+            mAppComponentFactory = createAppFactory(mApplicationInfo, mClassLoader);
 
             StrictMode.setThreadPolicy(oldPolicy);
             // Setup the class loader paths for profiling.
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index fb11272..fc5ea66 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -21,6 +21,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.pm.ActivityInfo;
+import android.content.res.ApkAssets;
 import android.content.res.AssetManager;
 import android.content.res.CompatResources;
 import android.content.res.CompatibilityInfo;
@@ -34,6 +35,7 @@
 import android.util.ArrayMap;
 import android.util.DisplayMetrics;
 import android.util.Log;
+import android.util.LruCache;
 import android.util.Pair;
 import android.util.Slog;
 import android.view.Display;
@@ -41,9 +43,13 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.IndentingPrintWriter;
 
+import java.io.IOException;
+import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Objects;
 import java.util.WeakHashMap;
 import java.util.function.Predicate;
@@ -59,12 +65,7 @@
      * Predicate that returns true if a WeakReference is gc'ed.
      */
     private static final Predicate<WeakReference<Resources>> sEmptyReferencePredicate =
-            new Predicate<WeakReference<Resources>>() {
-                @Override
-                public boolean test(WeakReference<Resources> weakRef) {
-                    return weakRef == null || weakRef.get() == null;
-                }
-            };
+            weakRef -> weakRef == null || weakRef.get() == null;
 
     /**
      * The global compatibility settings.
@@ -89,6 +90,48 @@
      */
     private final ArrayList<WeakReference<Resources>> mResourceReferences = new ArrayList<>();
 
+    private static class ApkKey {
+        public final String path;
+        public final boolean sharedLib;
+        public final boolean overlay;
+
+        ApkKey(String path, boolean sharedLib, boolean overlay) {
+            this.path = path;
+            this.sharedLib = sharedLib;
+            this.overlay = overlay;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = 1;
+            result = 31 * result + this.path.hashCode();
+            result = 31 * result + Boolean.hashCode(this.sharedLib);
+            result = 31 * result + Boolean.hashCode(this.overlay);
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof ApkKey)) {
+                return false;
+            }
+            ApkKey other = (ApkKey) obj;
+            return this.path.equals(other.path) && this.sharedLib == other.sharedLib
+                    && this.overlay == other.overlay;
+        }
+    }
+
+    /**
+     * The ApkAssets we are caching and intend to hold strong references to.
+     */
+    private final LruCache<ApkKey, ApkAssets> mLoadedApkAssets = new LruCache<>(15);
+
+    /**
+     * The ApkAssets that are being referenced in the wild that we can reuse, even if they aren't
+     * in our LRU cache. Bonus resources :)
+     */
+    private final ArrayMap<ApkKey, WeakReference<ApkAssets>> mCachedApkAssets = new ArrayMap<>();
+
     /**
      * Resources and base configuration override associated with an Activity.
      */
@@ -260,6 +303,43 @@
         }
     }
 
+    private static String overlayPathToIdmapPath(String path) {
+        return "/data/resource-cache/" + path.substring(1).replace('/', '@') + "@idmap";
+    }
+
+    private @NonNull ApkAssets loadApkAssets(String path, boolean sharedLib, boolean overlay)
+            throws IOException {
+        final ApkKey newKey = new ApkKey(path, sharedLib, overlay);
+        ApkAssets apkAssets = mLoadedApkAssets.get(newKey);
+        if (apkAssets != null) {
+            return apkAssets;
+        }
+
+        // Optimistically check if this ApkAssets exists somewhere else.
+        final WeakReference<ApkAssets> apkAssetsRef = mCachedApkAssets.get(newKey);
+        if (apkAssetsRef != null) {
+            apkAssets = apkAssetsRef.get();
+            if (apkAssets != null) {
+                mLoadedApkAssets.put(newKey, apkAssets);
+                return apkAssets;
+            } else {
+                // Clean up the reference.
+                mCachedApkAssets.remove(newKey);
+            }
+        }
+
+        // We must load this from disk.
+        if (overlay) {
+            apkAssets = ApkAssets.loadOverlayFromPath(overlayPathToIdmapPath(path),
+                    false /*system*/);
+        } else {
+            apkAssets = ApkAssets.loadFromPath(path, false /*system*/, sharedLib);
+        }
+        mLoadedApkAssets.put(newKey, apkAssets);
+        mCachedApkAssets.put(newKey, new WeakReference<>(apkAssets));
+        return apkAssets;
+    }
+
     /**
      * Creates an AssetManager from the paths within the ResourcesKey.
      *
@@ -270,13 +350,16 @@
     */
     @VisibleForTesting
     protected @Nullable AssetManager createAssetManager(@NonNull final ResourcesKey key) {
-        AssetManager assets = new AssetManager();
+        final AssetManager.Builder builder = new AssetManager.Builder();
 
         // resDir can be null if the 'android' package is creating a new Resources object.
         // This is fine, since each AssetManager automatically loads the 'android' package
         // already.
         if (key.mResDir != null) {
-            if (assets.addAssetPath(key.mResDir) == 0) {
+            try {
+                builder.addApkAssets(loadApkAssets(key.mResDir, false /*sharedLib*/,
+                        false /*overlay*/));
+            } catch (IOException e) {
                 Log.e(TAG, "failed to add asset path " + key.mResDir);
                 return null;
             }
@@ -284,7 +367,10 @@
 
         if (key.mSplitResDirs != null) {
             for (final String splitResDir : key.mSplitResDirs) {
-                if (assets.addAssetPath(splitResDir) == 0) {
+                try {
+                    builder.addApkAssets(loadApkAssets(splitResDir, false /*sharedLib*/,
+                            false /*overlay*/));
+                } catch (IOException e) {
                     Log.e(TAG, "failed to add split asset path " + splitResDir);
                     return null;
                 }
@@ -293,7 +379,14 @@
 
         if (key.mOverlayDirs != null) {
             for (final String idmapPath : key.mOverlayDirs) {
-                assets.addOverlayPath(idmapPath);
+                try {
+                    builder.addApkAssets(loadApkAssets(idmapPath, false /*sharedLib*/,
+                            true /*overlay*/));
+                } catch (IOException e) {
+                    Log.w(TAG, "failed to add overlay path " + idmapPath);
+
+                    // continue.
+                }
             }
         }
 
@@ -302,14 +395,73 @@
                 if (libDir.endsWith(".apk")) {
                     // Avoid opening files we know do not have resources,
                     // like code-only .jar files.
-                    if (assets.addAssetPathAsSharedLibrary(libDir) == 0) {
+                    try {
+                        builder.addApkAssets(loadApkAssets(libDir, true /*sharedLib*/,
+                                false /*overlay*/));
+                    } catch (IOException e) {
                         Log.w(TAG, "Asset path '" + libDir +
                                 "' does not exist or contains no resources.");
+
+                        // continue.
                     }
                 }
             }
         }
-        return assets;
+
+        return builder.build();
+    }
+
+    private static <T> int countLiveReferences(Collection<WeakReference<T>> collection) {
+        int count = 0;
+        for (WeakReference<T> ref : collection) {
+            final T value = ref != null ? ref.get() : null;
+            if (value != null) {
+                count++;
+            }
+        }
+        return count;
+    }
+
+    /**
+     * @hide
+     */
+    public void dump(String prefix, PrintWriter printWriter) {
+        synchronized (this) {
+            IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, "  ");
+            for (int i = 0; i < prefix.length() / 2; i++) {
+                pw.increaseIndent();
+            }
+
+            pw.println("ResourcesManager:");
+            pw.increaseIndent();
+            pw.print("cached apks: total=");
+            pw.print(mLoadedApkAssets.size());
+            pw.print(" created=");
+            pw.print(mLoadedApkAssets.createCount());
+            pw.print(" evicted=");
+            pw.print(mLoadedApkAssets.evictionCount());
+            pw.print(" hit=");
+            pw.print(mLoadedApkAssets.hitCount());
+            pw.print(" miss=");
+            pw.print(mLoadedApkAssets.missCount());
+            pw.print(" max=");
+            pw.print(mLoadedApkAssets.maxSize());
+            pw.println();
+
+            pw.print("total apks: ");
+            pw.println(countLiveReferences(mCachedApkAssets.values()));
+
+            pw.print("resources: ");
+
+            int references = countLiveReferences(mResourceReferences);
+            for (ActivityResources activityResources : mActivityResourceReferences.values()) {
+                references += countLiveReferences(activityResources.activityResources);
+            }
+            pw.println(references);
+
+            pw.print("resource impls: ");
+            pw.println(countLiveReferences(mResourceImpls.values()));
+        }
     }
 
     private Configuration generateConfig(@NonNull ResourcesKey key, @NonNull DisplayMetrics dm) {
@@ -630,28 +782,16 @@
 
                 // We will create the ResourcesImpl object outside of holding this lock.
             }
-        }
 
-        // If we're here, we didn't find a suitable ResourcesImpl to use, so create one now.
-        ResourcesImpl resourcesImpl = createResourcesImpl(key);
-        if (resourcesImpl == null) {
-            return null;
-        }
-
-        synchronized (this) {
-            ResourcesImpl existingResourcesImpl = findResourcesImplForKeyLocked(key);
-            if (existingResourcesImpl != null) {
-                if (DEBUG) {
-                    Slog.d(TAG, "- got beat! existing impl=" + existingResourcesImpl
-                            + " new impl=" + resourcesImpl);
-                }
-                resourcesImpl.getAssets().close();
-                resourcesImpl = existingResourcesImpl;
-            } else {
-                // Add this ResourcesImpl to the cache.
-                mResourceImpls.put(key, new WeakReference<>(resourcesImpl));
+            // If we're here, we didn't find a suitable ResourcesImpl to use, so create one now.
+            ResourcesImpl resourcesImpl = createResourcesImpl(key);
+            if (resourcesImpl == null) {
+                return null;
             }
 
+            // Add this ResourcesImpl to the cache.
+            mResourceImpls.put(key, new WeakReference<>(resourcesImpl));
+
             final Resources resources;
             if (activityToken != null) {
                 resources = getOrCreateResourcesForActivityLocked(activityToken, classLoader,
diff --git a/core/java/android/app/usage/IUsageStatsManager.aidl b/core/java/android/app/usage/IUsageStatsManager.aidl
index e72b84d..fff1a00 100644
--- a/core/java/android/app/usage/IUsageStatsManager.aidl
+++ b/core/java/android/app/usage/IUsageStatsManager.aidl
@@ -32,6 +32,7 @@
     ParceledListSlice queryConfigurationStats(int bucketType, long beginTime, long endTime,
             String callingPackage);
     UsageEvents queryEvents(long beginTime, long endTime, String callingPackage);
+    UsageEvents queryEventsForPackage(long beginTime, long endTime, String callingPackage);
     void setAppInactive(String packageName, boolean inactive, int userId);
     boolean isAppInactive(String packageName, int userId);
     void whitelistAppTemporarily(String packageName, long duration, int userId);
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 5a57b06..5f9fa43 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -52,10 +52,13 @@
  * </pre>
  * A request for data in the middle of a time interval will include that interval.
  * <p/>
- * <b>NOTE:</b> This API requires the permission android.permission.PACKAGE_USAGE_STATS.
- * However, declaring the permission implies intention to use the API and the user of the device
- * still needs to grant permission through the Settings application.
- * See {@link android.provider.Settings#ACTION_USAGE_ACCESS_SETTINGS}
+ * <b>NOTE:</b> Most methods on this API require the permission
+ * android.permission.PACKAGE_USAGE_STATS. However, declaring the permission implies intention to
+ * use the API and the user of the device still needs to grant permission through the Settings
+ * application.
+ * See {@link android.provider.Settings#ACTION_USAGE_ACCESS_SETTINGS}.
+ * Methods which only return the information for the calling package do not require this permission.
+ * E.g. {@link #getAppStandbyBucket()} and {@link #queryEventsForSelf(long, long)}.
  */
 @SystemService(Context.USAGE_STATS_SERVICE)
 public final class UsageStatsManager {
@@ -206,6 +209,8 @@
      * 2014 - com.example.charlie
      * </pre>
      *
+     * <p> The caller must have {@link android.Manifest.permission#PACKAGE_USAGE_STATS} </p>
+     *
      * @param intervalType The time interval by which the stats are aggregated.
      * @param beginTime The inclusive beginning of the range of stats to include in the results.
      * @param endTime The exclusive end of the range of stats to include in the results.
@@ -235,6 +240,7 @@
      * Gets the hardware configurations the device was in for the given time range, aggregated by
      * the specified interval. The results are ordered as in
      * {@link #queryUsageStats(int, long, long)}.
+     * <p> The caller must have {@link android.Manifest.permission#PACKAGE_USAGE_STATS} </p>
      *
      * @param intervalType The time interval by which the stats are aggregated.
      * @param beginTime The inclusive beginning of the range of stats to include in the results.
@@ -259,6 +265,7 @@
     /**
      * Query for events in the given time range. Events are only kept by the system for a few
      * days.
+     * <p> The caller must have {@link android.Manifest.permission#PACKAGE_USAGE_STATS} </p>
      *
      * @param beginTime The inclusive beginning of the range of events to include in the results.
      * @param endTime The exclusive end of the range of events to include in the results.
@@ -278,9 +285,32 @@
     }
 
     /**
+     * Like {@link #queryEvents(long, long)}, but only returns events for the calling package.
+     *
+     * @param beginTime The inclusive beginning of the range of events to include in the results.
+     * @param endTime The exclusive end of the range of events to include in the results.
+     * @return A {@link UsageEvents} object.
+     *
+     * @see #queryEvents(long, long)
+     */
+    public UsageEvents queryEventsForSelf(long beginTime, long endTime) {
+        try {
+            final UsageEvents events = mService.queryEventsForPackage(beginTime, endTime,
+                    mContext.getOpPackageName());
+            if (events != null) {
+                return events;
+            }
+        } catch (RemoteException e) {
+            // fallthrough
+        }
+        return sEmptyResults;
+    }
+
+    /**
      * A convenience method that queries for all stats in the given range (using the best interval
      * for that range), merges the resulting data, and keys it by package name.
      * See {@link #queryUsageStats(int, long, long)}.
+     * <p> The caller must have {@link android.Manifest.permission#PACKAGE_USAGE_STATS} </p>
      *
      * @param beginTime The inclusive beginning of the range of stats to include in the results.
      * @param endTime The exclusive end of the range of stats to include in the results.
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index b2c9edd4..f7649c9 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -763,15 +763,13 @@
     public String[] resourceDirs;
 
     /**
-     * String retrieved from the seinfo tag found in selinux policy. This value
-     * can be overridden with a value set through the mac_permissions.xml policy
-     * construct. This value is useful in setting an SELinux security context on
-     * the process as well as its data directory. The String default is being used
-     * here to represent a catchall label when no policy matches.
+     * String retrieved from the seinfo tag found in selinux policy. This value can be set through
+     * the mac_permissions.xml policy construct. This value is used for setting an SELinux security
+     * context on the process as well as its data directory.
      *
      * {@hide}
      */
-    public String seInfo = "default";
+    public String seInfo;
 
     /**
      * The seinfo tag generated per-user. This value may change based upon the
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 04a028b..5d5a978 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -54,6 +54,7 @@
 import android.content.pm.split.DefaultSplitAssetLoader;
 import android.content.pm.split.SplitAssetDependencyLoader;
 import android.content.pm.split.SplitAssetLoader;
+import android.content.res.ApkAssets;
 import android.content.res.AssetManager;
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -1287,7 +1288,6 @@
      */
     @Deprecated
     public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
-        final AssetManager assets = newConfiguredAssetManager();
         final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
         if (mOnlyCoreApps) {
             if (!lite.coreApp) {
@@ -1296,8 +1296,9 @@
             }
         }
 
+        final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags);
         try {
-            final Package pkg = parseBaseApk(apkFile, assets, flags);
+            final Package pkg = parseBaseApk(apkFile, assetLoader.getBaseAssetManager(), flags);
             pkg.setCodePath(apkFile.getCanonicalPath());
             pkg.setUse32bitAbi(lite.use32bitAbi);
             return pkg;
@@ -1305,28 +1306,10 @@
             throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
                     "Failed to get path: " + apkFile, e);
         } finally {
-            IoUtils.closeQuietly(assets);
+            IoUtils.closeQuietly(assetLoader);
         }
     }
 
-    private static int loadApkIntoAssetManager(AssetManager assets, String apkPath, int flags)
-            throws PackageParserException {
-        if ((flags & PARSE_MUST_BE_APK) != 0 && !isApkPath(apkPath)) {
-            throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
-                    "Invalid package file: " + apkPath);
-        }
-
-        // The AssetManager guarantees uniqueness for asset paths, so if this asset path
-        // already exists in the AssetManager, addAssetPath will only return the cookie
-        // assigned to it.
-        int cookie = assets.addAssetPath(apkPath);
-        if (cookie == 0) {
-            throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
-                    "Failed adding asset path: " + apkPath);
-        }
-        return cookie;
-    }
-
     private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
             throws PackageParserException {
         final String apkPath = apkFile.getAbsolutePath();
@@ -1342,13 +1325,15 @@
 
         if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
 
-        final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
-
-        Resources res = null;
         XmlResourceParser parser = null;
         try {
-            res = new Resources(assets, mMetrics, null);
+            final int cookie = assets.findCookieForPath(apkPath);
+            if (cookie == 0) {
+                throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
+                        "Failed adding asset path: " + apkPath);
+            }
             parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
+            final Resources res = new Resources(assets, mMetrics, null);
 
             final String[] outError = new String[1];
             final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
@@ -1383,15 +1368,18 @@
 
         if (DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath);
 
-        final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
-
         final Resources res;
         XmlResourceParser parser = null;
         try {
-            res = new Resources(assets, mMetrics, null);
-            assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                    Build.VERSION.RESOURCES_SDK_INT);
+            // This must always succeed, as the path has been added to the AssetManager before.
+            final int cookie = assets.findCookieForPath(apkPath);
+            if (cookie == 0) {
+                throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
+                        "Failed adding asset path: " + apkPath);
+            }
+
             parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
+            res = new Resources(assets, mMetrics, null);
 
             final String[] outError = new String[1];
             pkg = parseSplitApk(pkg, res, parser, flags, splitIndex, outError);
@@ -1593,21 +1581,19 @@
             int flags) throws PackageParserException {
         final String apkPath = fd != null ? debugPathName : apkFile.getAbsolutePath();
 
-        AssetManager assets = null;
         XmlResourceParser parser = null;
         try {
-            assets = newConfiguredAssetManager();
-            int cookie = fd != null
-                    ? assets.addAssetFd(fd, debugPathName) : assets.addAssetPath(apkPath);
-            if (cookie == 0) {
+            final ApkAssets apkAssets;
+            try {
+                apkAssets = fd != null
+                        ? ApkAssets.loadFromFd(fd, debugPathName, false, false)
+                        : ApkAssets.loadFromPath(apkPath);
+            } catch (IOException e) {
                 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
                         "Failed to parse " + apkPath);
             }
 
-            final DisplayMetrics metrics = new DisplayMetrics();
-            metrics.setToDefaults();
-
-            parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
+            parser = apkAssets.openXml(ANDROID_MANIFEST_FILENAME);
 
             final SigningDetails signingDetails;
             if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
@@ -1634,7 +1620,7 @@
                     "Failed to parse " + apkPath, e);
         } finally {
             IoUtils.closeQuietly(parser);
-            IoUtils.closeQuietly(assets);
+            // TODO(b/72056911): Implement and call close() on ApkAssets.
         }
     }
 
diff --git a/core/java/android/content/pm/split/DefaultSplitAssetLoader.java b/core/java/android/content/pm/split/DefaultSplitAssetLoader.java
index 99eb470..9e3a8f4 100644
--- a/core/java/android/content/pm/split/DefaultSplitAssetLoader.java
+++ b/core/java/android/content/pm/split/DefaultSplitAssetLoader.java
@@ -15,10 +15,13 @@
  */
 package android.content.pm.split;
 
-import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
+import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
 
 import android.content.pm.PackageParser;
+import android.content.pm.PackageParser.PackageParserException;
+import android.content.pm.PackageParser.ParseFlags;
+import android.content.res.ApkAssets;
 import android.content.res.AssetManager;
 import android.os.Build;
 
@@ -26,6 +29,8 @@
 
 import libcore.io.IoUtils;
 
+import java.io.IOException;
+
 /**
  * Loads the base and split APKs into a single AssetManager.
  * @hide
@@ -33,68 +38,66 @@
 public class DefaultSplitAssetLoader implements SplitAssetLoader {
     private final String mBaseCodePath;
     private final String[] mSplitCodePaths;
-    private final int mFlags;
-
+    private final @ParseFlags int mFlags;
     private AssetManager mCachedAssetManager;
 
-    public DefaultSplitAssetLoader(PackageParser.PackageLite pkg, int flags) {
+    public DefaultSplitAssetLoader(PackageParser.PackageLite pkg, @ParseFlags int flags) {
         mBaseCodePath = pkg.baseCodePath;
         mSplitCodePaths = pkg.splitCodePaths;
         mFlags = flags;
     }
 
-    private static void loadApkIntoAssetManager(AssetManager assets, String apkPath, int flags)
-            throws PackageParser.PackageParserException {
-        if ((flags & PackageParser.PARSE_MUST_BE_APK) != 0 && !PackageParser.isApkPath(apkPath)) {
-            throw new PackageParser.PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
-                    "Invalid package file: " + apkPath);
+    private static ApkAssets loadApkAssets(String path, @ParseFlags int flags)
+            throws PackageParserException {
+        if ((flags & PackageParser.PARSE_MUST_BE_APK) != 0 && !PackageParser.isApkPath(path)) {
+            throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
+                    "Invalid package file: " + path);
         }
 
-        if (assets.addAssetPath(apkPath) == 0) {
-            throw new PackageParser.PackageParserException(
-                    INSTALL_PARSE_FAILED_BAD_MANIFEST,
-                    "Failed adding asset path: " + apkPath);
+        try {
+            return ApkAssets.loadFromPath(path);
+        } catch (IOException e) {
+            throw new PackageParserException(INSTALL_FAILED_INVALID_APK,
+                    "Failed to load APK at path " + path, e);
         }
     }
 
     @Override
-    public AssetManager getBaseAssetManager() throws PackageParser.PackageParserException {
+    public AssetManager getBaseAssetManager() throws PackageParserException {
         if (mCachedAssetManager != null) {
             return mCachedAssetManager;
         }
 
-        AssetManager assets = new AssetManager();
-        try {
-            assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                    Build.VERSION.RESOURCES_SDK_INT);
-            loadApkIntoAssetManager(assets, mBaseCodePath, mFlags);
+        ApkAssets[] apkAssets = new ApkAssets[(mSplitCodePaths != null
+                ? mSplitCodePaths.length : 0) + 1];
 
-            if (!ArrayUtils.isEmpty(mSplitCodePaths)) {
-                for (String apkPath : mSplitCodePaths) {
-                    loadApkIntoAssetManager(assets, apkPath, mFlags);
-                }
-            }
+        // Load the base.
+        int splitIdx = 0;
+        apkAssets[splitIdx++] = loadApkAssets(mBaseCodePath, mFlags);
 
-            mCachedAssetManager = assets;
-            assets = null;
-            return mCachedAssetManager;
-        } finally {
-            if (assets != null) {
-                IoUtils.closeQuietly(assets);
+        // Load any splits.
+        if (!ArrayUtils.isEmpty(mSplitCodePaths)) {
+            for (String apkPath : mSplitCodePaths) {
+                apkAssets[splitIdx++] = loadApkAssets(apkPath, mFlags);
             }
         }
+
+        AssetManager assets = new AssetManager();
+        assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                Build.VERSION.RESOURCES_SDK_INT);
+        assets.setApkAssets(apkAssets, false /*invalidateCaches*/);
+
+        mCachedAssetManager = assets;
+        return mCachedAssetManager;
     }
 
     @Override
-    public AssetManager getSplitAssetManager(int splitIdx)
-            throws PackageParser.PackageParserException {
+    public AssetManager getSplitAssetManager(int splitIdx) throws PackageParserException {
         return getBaseAssetManager();
     }
 
     @Override
     public void close() throws Exception {
-        if (mCachedAssetManager != null) {
-            IoUtils.closeQuietly(mCachedAssetManager);
-        }
+        IoUtils.closeQuietly(mCachedAssetManager);
     }
 }
diff --git a/core/java/android/content/pm/split/SplitAssetDependencyLoader.java b/core/java/android/content/pm/split/SplitAssetDependencyLoader.java
index 16023f0..58eaabf 100644
--- a/core/java/android/content/pm/split/SplitAssetDependencyLoader.java
+++ b/core/java/android/content/pm/split/SplitAssetDependencyLoader.java
@@ -15,17 +15,21 @@
  */
 package android.content.pm.split;
 
-import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
 
 import android.annotation.NonNull;
+import android.content.pm.PackageManager;
 import android.content.pm.PackageParser;
+import android.content.pm.PackageParser.PackageParserException;
+import android.content.pm.PackageParser.ParseFlags;
+import android.content.res.ApkAssets;
 import android.content.res.AssetManager;
 import android.os.Build;
 import android.util.SparseArray;
 
 import libcore.io.IoUtils;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
 
@@ -34,17 +38,15 @@
  * is to be used when an application opts-in to isolated split loading.
  * @hide
  */
-public class SplitAssetDependencyLoader
-        extends SplitDependencyLoader<PackageParser.PackageParserException>
+public class SplitAssetDependencyLoader extends SplitDependencyLoader<PackageParserException>
         implements SplitAssetLoader {
     private final String[] mSplitPaths;
-    private final int mFlags;
-
-    private String[][] mCachedPaths;
-    private AssetManager[] mCachedAssetManagers;
+    private final @ParseFlags int mFlags;
+    private final ApkAssets[][] mCachedSplitApks;
+    private final AssetManager[] mCachedAssetManagers;
 
     public SplitAssetDependencyLoader(PackageParser.PackageLite pkg,
-            SparseArray<int[]> dependencies, int flags) {
+            SparseArray<int[]> dependencies, @ParseFlags int flags) {
         super(dependencies);
 
         // The base is inserted into index 0, so we need to shift all the splits by 1.
@@ -53,7 +55,7 @@
         System.arraycopy(pkg.splitCodePaths, 0, mSplitPaths, 1, pkg.splitCodePaths.length);
 
         mFlags = flags;
-        mCachedPaths = new String[mSplitPaths.length][];
+        mCachedSplitApks = new ApkAssets[mSplitPaths.length][];
         mCachedAssetManagers = new AssetManager[mSplitPaths.length];
     }
 
@@ -62,58 +64,60 @@
         return mCachedAssetManagers[splitIdx] != null;
     }
 
-    private static AssetManager createAssetManagerWithPaths(String[] assetPaths, int flags)
-            throws PackageParser.PackageParserException {
-        final AssetManager assets = new AssetManager();
-        try {
-            assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                    Build.VERSION.RESOURCES_SDK_INT);
-
-            for (String assetPath : assetPaths) {
-                if ((flags & PackageParser.PARSE_MUST_BE_APK) != 0 &&
-                        !PackageParser.isApkPath(assetPath)) {
-                    throw new PackageParser.PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
-                            "Invalid package file: " + assetPath);
-                }
-
-                if (assets.addAssetPath(assetPath) == 0) {
-                    throw new PackageParser.PackageParserException(
-                            INSTALL_PARSE_FAILED_BAD_MANIFEST,
-                            "Failed adding asset path: " + assetPath);
-                }
-            }
-            return assets;
-        } catch (Throwable e) {
-            IoUtils.closeQuietly(assets);
-            throw e;
+    private static ApkAssets loadApkAssets(String path, @ParseFlags int flags)
+            throws PackageParserException {
+        if ((flags & PackageParser.PARSE_MUST_BE_APK) != 0 && !PackageParser.isApkPath(path)) {
+            throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
+                    "Invalid package file: " + path);
         }
+
+        try {
+            return ApkAssets.loadFromPath(path);
+        } catch (IOException e) {
+            throw new PackageParserException(PackageManager.INSTALL_FAILED_INVALID_APK,
+                    "Failed to load APK at path " + path, e);
+        }
+    }
+
+    private static AssetManager createAssetManagerWithAssets(ApkAssets[] apkAssets) {
+        final AssetManager assets = new AssetManager();
+        assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                Build.VERSION.RESOURCES_SDK_INT);
+        assets.setApkAssets(apkAssets, false /*invalidateCaches*/);
+        return assets;
     }
 
     @Override
     protected void constructSplit(int splitIdx, @NonNull int[] configSplitIndices,
-            int parentSplitIdx) throws PackageParser.PackageParserException {
-        final ArrayList<String> assetPaths = new ArrayList<>();
+            int parentSplitIdx) throws PackageParserException {
+        final ArrayList<ApkAssets> assets = new ArrayList<>();
+
+        // Include parent ApkAssets.
         if (parentSplitIdx >= 0) {
-            Collections.addAll(assetPaths, mCachedPaths[parentSplitIdx]);
+            Collections.addAll(assets, mCachedSplitApks[parentSplitIdx]);
         }
 
-        assetPaths.add(mSplitPaths[splitIdx]);
+        // Include this ApkAssets.
+        assets.add(loadApkAssets(mSplitPaths[splitIdx], mFlags));
+
+        // Load and include all config splits for this feature.
         for (int configSplitIdx : configSplitIndices) {
-            assetPaths.add(mSplitPaths[configSplitIdx]);
+            assets.add(loadApkAssets(mSplitPaths[configSplitIdx], mFlags));
         }
-        mCachedPaths[splitIdx] = assetPaths.toArray(new String[assetPaths.size()]);
-        mCachedAssetManagers[splitIdx] = createAssetManagerWithPaths(mCachedPaths[splitIdx],
-                mFlags);
+
+        // Cache the results.
+        mCachedSplitApks[splitIdx] = assets.toArray(new ApkAssets[assets.size()]);
+        mCachedAssetManagers[splitIdx] = createAssetManagerWithAssets(mCachedSplitApks[splitIdx]);
     }
 
     @Override
-    public AssetManager getBaseAssetManager() throws PackageParser.PackageParserException {
+    public AssetManager getBaseAssetManager() throws PackageParserException {
         loadDependenciesForSplit(0);
         return mCachedAssetManagers[0];
     }
 
     @Override
-    public AssetManager getSplitAssetManager(int idx) throws PackageParser.PackageParserException {
+    public AssetManager getSplitAssetManager(int idx) throws PackageParserException {
         // Since we insert the base at position 0, and PackageParser keeps splits separate from
         // the base, we need to adjust the index.
         loadDependenciesForSplit(idx + 1);
diff --git a/core/java/android/content/res/ApkAssets.java b/core/java/android/content/res/ApkAssets.java
new file mode 100644
index 0000000..9de8be3
--- /dev/null
+++ b/core/java/android/content/res/ApkAssets.java
@@ -0,0 +1,195 @@
+/*
+ * 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 android.content.res;
+
+import android.annotation.NonNull;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.Preconditions;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+
+/**
+ * The loaded, immutable, in-memory representation of an APK.
+ *
+ * The main implementation is native C++ and there is very little API surface exposed here. The APK
+ * is mainly accessed via {@link AssetManager}.
+ *
+ * Since the ApkAssets instance is immutable, it can be reused and shared across AssetManagers,
+ * making the creation of AssetManagers very cheap.
+ * @hide
+ */
+public final class ApkAssets {
+    @GuardedBy("this") private final long mNativePtr;
+    @GuardedBy("this") private StringBlock mStringBlock;
+
+    /**
+     * Creates a new ApkAssets instance from the given path on disk.
+     *
+     * @param path The path to an APK on disk.
+     * @return a new instance of ApkAssets.
+     * @throws IOException if a disk I/O error or parsing error occurred.
+     */
+    public static @NonNull ApkAssets loadFromPath(@NonNull String path) throws IOException {
+        return new ApkAssets(path, false /*system*/, false /*forceSharedLib*/, false /*overlay*/);
+    }
+
+    /**
+     * Creates a new ApkAssets instance from the given path on disk.
+     *
+     * @param path The path to an APK on disk.
+     * @param system When true, the APK is loaded as a system APK (framework).
+     * @return a new instance of ApkAssets.
+     * @throws IOException if a disk I/O error or parsing error occurred.
+     */
+    public static @NonNull ApkAssets loadFromPath(@NonNull String path, boolean system)
+            throws IOException {
+        return new ApkAssets(path, system, false /*forceSharedLib*/, false /*overlay*/);
+    }
+
+    /**
+     * Creates a new ApkAssets instance from the given path on disk.
+     *
+     * @param path The path to an APK on disk.
+     * @param system When true, the APK is loaded as a system APK (framework).
+     * @param forceSharedLibrary When true, any packages within the APK with package ID 0x7f are
+     *                           loaded as a shared library.
+     * @return a new instance of ApkAssets.
+     * @throws IOException if a disk I/O error or parsing error occurred.
+     */
+    public static @NonNull ApkAssets loadFromPath(@NonNull String path, boolean system,
+            boolean forceSharedLibrary) throws IOException {
+        return new ApkAssets(path, system, forceSharedLibrary, false /*overlay*/);
+    }
+
+    /**
+     * Creates a new ApkAssets instance from the given file descriptor. Not for use by applications.
+     *
+     * Performs a dup of the underlying fd, so you must take care of still closing
+     * the FileDescriptor yourself (and can do that whenever you want).
+     *
+     * @param fd The FileDescriptor of an open, readable APK.
+     * @param friendlyName The friendly name used to identify this ApkAssets when logging.
+     * @param system When true, the APK is loaded as a system APK (framework).
+     * @param forceSharedLibrary When true, any packages within the APK with package ID 0x7f are
+     *                           loaded as a shared library.
+     * @return a new instance of ApkAssets.
+     * @throws IOException if a disk I/O error or parsing error occurred.
+     */
+    public static @NonNull ApkAssets loadFromFd(@NonNull FileDescriptor fd,
+            @NonNull String friendlyName, boolean system, boolean forceSharedLibrary)
+            throws IOException {
+        return new ApkAssets(fd, friendlyName, system, forceSharedLibrary);
+    }
+
+    /**
+     * Creates a new ApkAssets instance from the IDMAP at idmapPath. The overlay APK path
+     * is encoded within the IDMAP.
+     *
+     * @param idmapPath Path to the IDMAP of an overlay APK.
+     * @param system When true, the APK is loaded as a system APK (framework).
+     * @return a new instance of ApkAssets.
+     * @throws IOException if a disk I/O error or parsing error occurred.
+     */
+    public static @NonNull ApkAssets loadOverlayFromPath(@NonNull String idmapPath, boolean system)
+            throws IOException {
+        return new ApkAssets(idmapPath, system, false /*forceSharedLibrary*/, true /*overlay*/);
+    }
+
+    private ApkAssets(@NonNull String path, boolean system, boolean forceSharedLib, boolean overlay)
+            throws IOException {
+        Preconditions.checkNotNull(path, "path");
+        mNativePtr = nativeLoad(path, system, forceSharedLib, overlay);
+        mStringBlock = new StringBlock(nativeGetStringBlock(mNativePtr), true /*useSparse*/);
+    }
+
+    private ApkAssets(@NonNull FileDescriptor fd, @NonNull String friendlyName, boolean system,
+            boolean forceSharedLib) throws IOException {
+        Preconditions.checkNotNull(fd, "fd");
+        Preconditions.checkNotNull(friendlyName, "friendlyName");
+        mNativePtr = nativeLoadFromFd(fd, friendlyName, system, forceSharedLib);
+        mStringBlock = new StringBlock(nativeGetStringBlock(mNativePtr), true /*useSparse*/);
+    }
+
+    public @NonNull String getAssetPath() {
+        synchronized (this) {
+            return nativeGetAssetPath(mNativePtr);
+        }
+    }
+
+    CharSequence getStringFromPool(int idx) {
+        synchronized (this) {
+            return mStringBlock.get(idx);
+        }
+    }
+
+    /**
+     * Retrieve a parser for a compiled XML file. This is associated with a single APK and
+     * <em>NOT</em> a full AssetManager. This means that shared-library references will not be
+     * dynamically assigned runtime package IDs.
+     *
+     * @param fileName The path to the file within the APK.
+     * @return An XmlResourceParser.
+     * @throws IOException if the file was not found or an error occurred retrieving it.
+     */
+    public @NonNull XmlResourceParser openXml(@NonNull String fileName) throws IOException {
+        Preconditions.checkNotNull(fileName, "fileName");
+        synchronized (this) {
+            long nativeXmlPtr = nativeOpenXml(mNativePtr, fileName);
+            try (XmlBlock block = new XmlBlock(null, nativeXmlPtr)) {
+                XmlResourceParser parser = block.newParser();
+                // If nativeOpenXml doesn't throw, it will always return a valid native pointer,
+                // which makes newParser always return non-null. But let's be paranoid.
+                if (parser == null) {
+                    throw new AssertionError("block.newParser() returned a null parser");
+                }
+                return parser;
+            }
+        }
+    }
+
+    /**
+     * Returns false if the underlying APK was changed since this ApkAssets was loaded.
+     */
+    public boolean isUpToDate() {
+        synchronized (this) {
+            return nativeIsUpToDate(mNativePtr);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "ApkAssets{path=" + getAssetPath() + "}";
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        nativeDestroy(mNativePtr);
+    }
+
+    private static native long nativeLoad(
+            @NonNull String path, boolean system, boolean forceSharedLib, boolean overlay)
+            throws IOException;
+    private static native long nativeLoadFromFd(@NonNull FileDescriptor fd,
+            @NonNull String friendlyName, boolean system, boolean forceSharedLib)
+            throws IOException;
+    private static native void nativeDestroy(long ptr);
+    private static native @NonNull String nativeGetAssetPath(long ptr);
+    private static native long nativeGetStringBlock(long ptr);
+    private static native boolean nativeIsUpToDate(long ptr);
+    private static native long nativeOpenXml(long ptr, @NonNull String fileName) throws IOException;
+}
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 5f8a34d..2895342 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -18,22 +18,33 @@
 
 import android.annotation.AnyRes;
 import android.annotation.ArrayRes;
+import android.annotation.AttrRes;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StringRes;
+import android.annotation.StyleRes;
 import android.content.pm.ActivityInfo;
 import android.content.res.Configuration.NativeConfig;
 import android.os.ParcelFileDescriptor;
+import android.util.ArraySet;
 import android.util.Log;
 import android.util.SparseArray;
 import android.util.TypedValue;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.Preconditions;
 
-import java.io.FileDescriptor;
+import libcore.io.IoUtils;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.channels.FileLock;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 
 /**
@@ -44,7 +55,20 @@
  * bytes.
  */
 public final class AssetManager implements AutoCloseable {
-    /* modes used when opening an asset */
+    private static final String TAG = "AssetManager";
+    private static final boolean DEBUG_REFS = false;
+
+    private static final String FRAMEWORK_APK_PATH = "/system/framework/framework-res.apk";
+
+    private static final Object sSync = new Object();
+
+    private static final ApkAssets[] sEmptyApkAssets = new ApkAssets[0];
+
+    // Not private for LayoutLib's BridgeAssetManager.
+    @GuardedBy("sSync") static AssetManager sSystem = null;
+
+    @GuardedBy("sSync") private static ApkAssets[] sSystemApkAssets = new ApkAssets[0];
+    @GuardedBy("sSync") private static ArraySet<ApkAssets> sSystemApkAssetsSet;
 
     /**
      * Mode for {@link #open(String, int)}: no specific information about how
@@ -67,146 +91,358 @@
      */
     public static final int ACCESS_BUFFER = 3;
 
-    private static final String TAG = "AssetManager";
-    private static final boolean localLOGV = false || false;
-    
-    private static final boolean DEBUG_REFS = false;
-    
-    private static final Object sSync = new Object();
-    /*package*/ static AssetManager sSystem = null;
+    @GuardedBy("this") private final TypedValue mValue = new TypedValue();
+    @GuardedBy("this") private final long[] mOffsets = new long[2];
 
-    private final TypedValue mValue = new TypedValue();
-    private final long[] mOffsets = new long[2];
-    
-    // For communication with native code.
-    private long mObject;
+    // Pointer to native implementation, stuffed inside a long.
+    @GuardedBy("this") private long mObject;
 
-    private StringBlock mStringBlocks[] = null;
-    
-    private int mNumRefs = 1;
-    private boolean mOpen = true;
-    private HashMap<Long, RuntimeException> mRefStacks;
- 
+    // The loaded asset paths.
+    @GuardedBy("this") private ApkAssets[] mApkAssets;
+
+    // Debug/reference counting implementation.
+    @GuardedBy("this") private boolean mOpen = true;
+    @GuardedBy("this") private int mNumRefs = 1;
+    @GuardedBy("this") private HashMap<Long, RuntimeException> mRefStacks;
+
+    /**
+     * A Builder class that helps create an AssetManager with only a single invocation of
+     * {@link AssetManager#setApkAssets(ApkAssets[], boolean)}. Without using this builder,
+     * AssetManager must ensure there are system ApkAssets loaded at all times, which when combined
+     * with the user's call to add additional ApkAssets, results in multiple calls to
+     * {@link AssetManager#setApkAssets(ApkAssets[], boolean)}.
+     * @hide
+     */
+    public static class Builder {
+        private ArrayList<ApkAssets> mUserApkAssets = new ArrayList<>();
+
+        public Builder addApkAssets(ApkAssets apkAssets) {
+            mUserApkAssets.add(apkAssets);
+            return this;
+        }
+
+        public AssetManager build() {
+            // Retrieving the system ApkAssets forces their creation as well.
+            final ApkAssets[] systemApkAssets = getSystem().getApkAssets();
+
+            final int totalApkAssetCount = systemApkAssets.length + mUserApkAssets.size();
+            final ApkAssets[] apkAssets = new ApkAssets[totalApkAssetCount];
+
+            System.arraycopy(systemApkAssets, 0, apkAssets, 0, systemApkAssets.length);
+
+            final int userApkAssetCount = mUserApkAssets.size();
+            for (int i = 0; i < userApkAssetCount; i++) {
+                apkAssets[i + systemApkAssets.length] = mUserApkAssets.get(i);
+            }
+
+            // Calling this constructor prevents creation of system ApkAssets, which we took care
+            // of in this Builder.
+            final AssetManager assetManager = new AssetManager(false /*sentinel*/);
+            assetManager.mApkAssets = apkAssets;
+            AssetManager.nativeSetApkAssets(assetManager.mObject, apkAssets,
+                    false /*invalidateCaches*/);
+            return assetManager;
+        }
+    }
+
     /**
      * Create a new AssetManager containing only the basic system assets.
      * Applications will not generally use this method, instead retrieving the
      * appropriate asset manager with {@link Resources#getAssets}.    Not for
      * use by applications.
-     * {@hide}
+     * @hide
      */
     public AssetManager() {
-        synchronized (this) {
-            if (DEBUG_REFS) {
-                mNumRefs = 0;
-                incRefsLocked(this.hashCode());
-            }
-            init(false);
-            if (localLOGV) Log.v(TAG, "New asset manager: " + this);
-            ensureSystemAssets();
+        final ApkAssets[] assets;
+        synchronized (sSync) {
+            createSystemAssetsInZygoteLocked();
+            assets = sSystemApkAssets;
+        }
+
+        mObject = nativeCreate();
+        if (DEBUG_REFS) {
+            mNumRefs = 0;
+            incRefsLocked(hashCode());
+        }
+
+        // Always set the framework resources.
+        setApkAssets(assets, false /*invalidateCaches*/);
+    }
+
+    /**
+     * Private constructor that doesn't call ensureSystemAssets.
+     * Used for the creation of system assets.
+     */
+    @SuppressWarnings("unused")
+    private AssetManager(boolean sentinel) {
+        mObject = nativeCreate();
+        if (DEBUG_REFS) {
+            mNumRefs = 0;
+            incRefsLocked(hashCode());
         }
     }
 
-    private static void ensureSystemAssets() {
-        synchronized (sSync) {
-            if (sSystem == null) {
-                AssetManager system = new AssetManager(true);
-                system.makeStringBlocks(null);
-                sSystem = system;
-            }
+    /**
+     * This must be called from Zygote so that system assets are shared by all applications.
+     */
+    @GuardedBy("sSync")
+    private static void createSystemAssetsInZygoteLocked() {
+        if (sSystem != null) {
+            return;
+        }
+
+        // Make sure that all IDMAPs are up to date.
+        nativeVerifySystemIdmaps();
+
+        try {
+            final ArrayList<ApkAssets> apkAssets = new ArrayList<>();
+            apkAssets.add(ApkAssets.loadFromPath(FRAMEWORK_APK_PATH, true /*system*/));
+            loadStaticRuntimeOverlays(apkAssets);
+
+            sSystemApkAssetsSet = new ArraySet<>(apkAssets);
+            sSystemApkAssets = apkAssets.toArray(new ApkAssets[apkAssets.size()]);
+            sSystem = new AssetManager(true /*sentinel*/);
+            sSystem.setApkAssets(sSystemApkAssets, false /*invalidateCaches*/);
+        } catch (IOException e) {
+            throw new IllegalStateException("Failed to create system AssetManager", e);
         }
     }
-    
-    private AssetManager(boolean isSystem) {
-        if (DEBUG_REFS) {
-            synchronized (this) {
-                mNumRefs = 0;
-                incRefsLocked(this.hashCode());
-            }
+
+    /**
+     * Loads the static runtime overlays declared in /data/resource-cache/overlays.list.
+     * Throws an exception if the file is corrupt or if loading the APKs referenced by the file
+     * fails. Returns quietly if the overlays.list file doesn't exist.
+     * @param outApkAssets The list to fill with the loaded ApkAssets.
+     */
+    private static void loadStaticRuntimeOverlays(ArrayList<ApkAssets> outApkAssets)
+            throws IOException {
+        final FileInputStream fis;
+        try {
+            fis = new FileInputStream("/data/resource-cache/overlays.list");
+        } catch (FileNotFoundException e) {
+            // We might not have any overlays, this is fine. We catch here since ApkAssets
+            // loading can also fail with the same exception, which we would want to propagate.
+            Log.i(TAG, "no overlays.list file found");
+            return;
         }
-        init(true);
-        if (localLOGV) Log.v(TAG, "New asset manager: " + this);
+
+        try {
+            // Acquire a lock so that any idmap scanning doesn't impact the current set.
+            // The order of this try-with-resources block matters. We must release the lock, and
+            // then close the file streams when exiting the block.
+            try (final BufferedReader br = new BufferedReader(new InputStreamReader(fis));
+                 final FileLock flock = fis.getChannel().lock(0, Long.MAX_VALUE, true /*shared*/)) {
+                for (String line; (line = br.readLine()) != null; ) {
+                    final String idmapPath = line.split(" ")[1];
+                    outApkAssets.add(ApkAssets.loadOverlayFromPath(idmapPath, true /*system*/));
+                }
+            }
+        } finally {
+            // When BufferedReader is closed above, FileInputStream is closed as well. But let's be
+            // paranoid.
+            IoUtils.closeQuietly(fis);
+        }
     }
 
     /**
      * Return a global shared asset manager that provides access to only
      * system assets (no application assets).
-     * {@hide}
+     * @hide
      */
     public static AssetManager getSystem() {
-        ensureSystemAssets();
-        return sSystem;
+        synchronized (sSync) {
+            createSystemAssetsInZygoteLocked();
+            return sSystem;
+        }
     }
 
     /**
      * Close this asset manager.
      */
+    @Override
     public void close() {
-        synchronized(this) {
-            //System.out.println("Release: num=" + mNumRefs
-            //                   + ", released=" + mReleased);
+        synchronized (this) {
+            if (!mOpen) {
+                return;
+            }
+
+            mOpen = false;
+            decRefsLocked(hashCode());
+        }
+    }
+
+    /**
+     * Changes the asset paths in this AssetManager. This replaces the {@link #addAssetPath(String)}
+     * family of methods.
+     *
+     * @param apkAssets The new set of paths.
+     * @param invalidateCaches Whether to invalidate any caches. This should almost always be true.
+     *                         Set this to false if you are appending new resources
+     *                         (not new configurations).
+     * @hide
+     */
+    public void setApkAssets(@NonNull ApkAssets[] apkAssets, boolean invalidateCaches) {
+        Preconditions.checkNotNull(apkAssets, "apkAssets");
+
+        ApkAssets[] newApkAssets = new ApkAssets[sSystemApkAssets.length + apkAssets.length];
+
+        // Copy the system assets first.
+        System.arraycopy(sSystemApkAssets, 0, newApkAssets, 0, sSystemApkAssets.length);
+
+        // Copy the given ApkAssets if they are not already in the system list.
+        int newLength = sSystemApkAssets.length;
+        for (ApkAssets apkAsset : apkAssets) {
+            if (!sSystemApkAssetsSet.contains(apkAsset)) {
+                newApkAssets[newLength++] = apkAsset;
+            }
+        }
+
+        // Truncate if necessary.
+        if (newLength != newApkAssets.length) {
+            newApkAssets = Arrays.copyOf(newApkAssets, newLength);
+        }
+
+        synchronized (this) {
+            ensureOpenLocked();
+            mApkAssets = newApkAssets;
+            nativeSetApkAssets(mObject, mApkAssets, invalidateCaches);
+            if (invalidateCaches) {
+                // Invalidate all caches.
+                invalidateCachesLocked(-1);
+            }
+        }
+    }
+
+    /**
+     * Invalidates the caches in this AssetManager according to the bitmask `diff`.
+     *
+     * @param diff The bitmask of changes generated by {@link Configuration#diff(Configuration)}.
+     * @see ActivityInfo.Config
+     */
+    private void invalidateCachesLocked(int diff) {
+        // TODO(adamlesinski): Currently there are no caches to invalidate in Java code.
+    }
+
+    /**
+     * Returns the set of ApkAssets loaded by this AssetManager. If the AssetManager is closed, this
+     * returns a 0-length array.
+     * @hide
+     */
+    public @NonNull ApkAssets[] getApkAssets() {
+        synchronized (this) {
             if (mOpen) {
-                mOpen = false;
-                decRefsLocked(this.hashCode());
+                return mApkAssets;
             }
         }
+        return sEmptyApkAssets;
     }
 
     /**
-     * Retrieves the string value associated with a particular resource
-     * identifier for the current configuration.
-     *
-     * @param resId the resource identifier to load
-     * @return the string value, or {@code null}
+     * Returns a cookie for use with the other APIs of AssetManager.
+     * @return 0 if the path was not found, otherwise a positive integer cookie representing
+     * this path in the AssetManager.
+     * @hide
      */
-    @Nullable
-    final CharSequence getResourceText(@StringRes int resId) {
+    public int findCookieForPath(@NonNull String path) {
+        Preconditions.checkNotNull(path, "path");
         synchronized (this) {
-            final TypedValue outValue = mValue;
-            if (getResourceValue(resId, 0, outValue, true)) {
-                return outValue.coerceToString();
+            ensureValidLocked();
+            final int count = mApkAssets.length;
+            for (int i = 0; i < count; i++) {
+                if (path.equals(mApkAssets[i].getAssetPath())) {
+                    return i + 1;
+                }
             }
-            return null;
         }
+        return 0;
     }
 
     /**
-     * Retrieves the string value associated with a particular resource
-     * identifier for the current configuration.
-     *
-     * @param resId the resource identifier to load
-     * @param bagEntryId
-     * @return the string value, or {@code null}
+     * @deprecated Use {@link #setApkAssets(ApkAssets[], boolean)}
+     * @hide
      */
-    @Nullable
-    final CharSequence getResourceBagText(@StringRes int resId, int bagEntryId) {
+    @Deprecated
+    public int addAssetPath(String path) {
+        return addAssetPathInternal(path, false /*overlay*/, false /*appAsLib*/);
+    }
+
+    /**
+     * @deprecated Use {@link #setApkAssets(ApkAssets[], boolean)}
+     * @hide
+     */
+    @Deprecated
+    public int addAssetPathAsSharedLibrary(String path) {
+        return addAssetPathInternal(path, false /*overlay*/, true /*appAsLib*/);
+    }
+
+    /**
+     * @deprecated Use {@link #setApkAssets(ApkAssets[], boolean)}
+     * @hide
+     */
+    @Deprecated
+    public int addOverlayPath(String path) {
+        return addAssetPathInternal(path, true /*overlay*/, false /*appAsLib*/);
+    }
+
+    private int addAssetPathInternal(String path, boolean overlay, boolean appAsLib) {
+        Preconditions.checkNotNull(path, "path");
         synchronized (this) {
-            final TypedValue outValue = mValue;
-            final int block = loadResourceBagValue(resId, bagEntryId, outValue, true);
-            if (block < 0) {
-                return null;
+            ensureOpenLocked();
+            final int count = mApkAssets.length;
+
+            // See if we already have it loaded.
+            for (int i = 0; i < count; i++) {
+                if (mApkAssets[i].getAssetPath().equals(path)) {
+                    return i + 1;
+                }
             }
 
-            // Convert the changing configurations flags populated by native code.
-            outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
-                    outValue.changingConfigurations);
-
-            if (outValue.type == TypedValue.TYPE_STRING) {
-                return mStringBlocks[block].get(outValue.data);
+            final ApkAssets assets;
+            try {
+                if (overlay) {
+                    // TODO(b/70343104): This hardcoded path will be removed once
+                    // addAssetPathInternal is deleted.
+                    final String idmapPath = "/data/resource-cache/"
+                            + path.substring(1).replace('/', '@')
+                            + "@idmap";
+                    assets = ApkAssets.loadOverlayFromPath(idmapPath, false /*system*/);
+                } else {
+                    assets = ApkAssets.loadFromPath(path, false /*system*/, appAsLib);
+                }
+            } catch (IOException e) {
+                return 0;
             }
-            return outValue.coerceToString();
+
+            mApkAssets = Arrays.copyOf(mApkAssets, count + 1);
+            mApkAssets[count] = assets;
+            nativeSetApkAssets(mObject, mApkAssets, true);
+            invalidateCachesLocked(-1);
+            return count + 1;
         }
     }
 
     /**
-     * Retrieves the string array associated with a particular resource
-     * identifier for the current configuration.
-     *
-     * @param resId the resource identifier of the string array
-     * @return the string array, or {@code null}
+     * Ensures that the native implementation has not been destroyed.
+     * The AssetManager may have been closed, but references to it still exist
+     * and therefore the native implementation is not destroyed.
      */
-    @Nullable
-    final String[] getResourceStringArray(@ArrayRes int resId) {
-        return getArrayStringResource(resId);
+    @GuardedBy("this")
+    private void ensureValidLocked() {
+        if (mObject == 0) {
+            throw new RuntimeException("AssetManager has been destroyed");
+        }
+    }
+
+    /**
+     * Ensures that the AssetManager has not been explicitly closed. If this method passes,
+     * then this implies that ensureValidLocked() also passes.
+     */
+    @GuardedBy("this")
+    private void ensureOpenLocked() {
+        // If mOpen is true, this implies that mObject != 0.
+        if (!mOpen) {
+            throw new RuntimeException("AssetManager has been closed");
+        }
     }
 
     /**
@@ -221,11 +457,14 @@
      * @return {@code true} if the data was loaded into {@code outValue},
      *         {@code false} otherwise
      */
-    final boolean getResourceValue(@AnyRes int resId, int densityDpi, @NonNull TypedValue outValue,
+    boolean getResourceValue(@AnyRes int resId, int densityDpi, @NonNull TypedValue outValue,
             boolean resolveRefs) {
+        Preconditions.checkNotNull(outValue, "outValue");
         synchronized (this) {
-            final int block = loadResourceValue(resId, (short) densityDpi, outValue, resolveRefs);
-            if (block < 0) {
+            ensureValidLocked();
+            final int cookie = nativeGetResourceValue(
+                    mObject, resId, (short) densityDpi, outValue, resolveRefs);
+            if (cookie <= 0) {
                 return false;
             }
 
@@ -234,38 +473,156 @@
                     outValue.changingConfigurations);
 
             if (outValue.type == TypedValue.TYPE_STRING) {
-                outValue.string = mStringBlocks[block].get(outValue.data);
+                outValue.string = mApkAssets[cookie - 1].getStringFromPool(outValue.data);
             }
             return true;
         }
     }
 
     /**
+     * Retrieves the string value associated with a particular resource
+     * identifier for the current configuration.
+     *
+     * @param resId the resource identifier to load
+     * @return the string value, or {@code null}
+     */
+    @Nullable CharSequence getResourceText(@StringRes int resId) {
+        synchronized (this) {
+            final TypedValue outValue = mValue;
+            if (getResourceValue(resId, 0, outValue, true)) {
+                return outValue.coerceToString();
+            }
+            return null;
+        }
+    }
+
+    /**
+     * Retrieves the string value associated with a particular resource
+     * identifier for the current configuration.
+     *
+     * @param resId the resource identifier to load
+     * @param bagEntryId the index into the bag to load
+     * @return the string value, or {@code null}
+     */
+    @Nullable CharSequence getResourceBagText(@StringRes int resId, int bagEntryId) {
+        synchronized (this) {
+            ensureValidLocked();
+            final TypedValue outValue = mValue;
+            final int cookie = nativeGetResourceBagValue(mObject, resId, bagEntryId, outValue);
+            if (cookie <= 0) {
+                return null;
+            }
+
+            // Convert the changing configurations flags populated by native code.
+            outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
+                    outValue.changingConfigurations);
+
+            if (outValue.type == TypedValue.TYPE_STRING) {
+                return mApkAssets[cookie - 1].getStringFromPool(outValue.data);
+            }
+            return outValue.coerceToString();
+        }
+    }
+
+    int getResourceArraySize(@ArrayRes int resId) {
+        synchronized (this) {
+            ensureValidLocked();
+            return nativeGetResourceArraySize(mObject, resId);
+        }
+    }
+
+    /**
+     * Populates `outData` with array elements of `resId`. `outData` is normally
+     * used with
+     * {@link TypedArray}.
+     *
+     * Each logical element in `outData` is {@link TypedArray#STYLE_NUM_ENTRIES}
+     * long,
+     * with the indices of the data representing the type, value, asset cookie,
+     * resource ID,
+     * configuration change mask, and density of the element.
+     *
+     * @param resId The resource ID of an array resource.
+     * @param outData The array to populate with data.
+     * @return The length of the array.
+     *
+     * @see TypedArray#STYLE_TYPE
+     * @see TypedArray#STYLE_DATA
+     * @see TypedArray#STYLE_ASSET_COOKIE
+     * @see TypedArray#STYLE_RESOURCE_ID
+     * @see TypedArray#STYLE_CHANGING_CONFIGURATIONS
+     * @see TypedArray#STYLE_DENSITY
+     */
+    int getResourceArray(@ArrayRes int resId, @NonNull int[] outData) {
+        Preconditions.checkNotNull(outData, "outData");
+        synchronized (this) {
+            ensureValidLocked();
+            return nativeGetResourceArray(mObject, resId, outData);
+        }
+    }
+
+    /**
+     * Retrieves the string array associated with a particular resource
+     * identifier for the current configuration.
+     *
+     * @param resId the resource identifier of the string array
+     * @return the string array, or {@code null}
+     */
+    @Nullable String[] getResourceStringArray(@ArrayRes int resId) {
+        synchronized (this) {
+            ensureValidLocked();
+            return nativeGetResourceStringArray(mObject, resId);
+        }
+    }
+
+    /**
      * Retrieve the text array associated with a particular resource
      * identifier.
      *
      * @param resId the resource id of the string array
      */
-    final @Nullable CharSequence[] getResourceTextArray(@ArrayRes int resId) {
+    @Nullable CharSequence[] getResourceTextArray(@ArrayRes int resId) {
         synchronized (this) {
-            final int[] rawInfoArray = getArrayStringInfo(resId);
+            ensureValidLocked();
+            final int[] rawInfoArray = nativeGetResourceStringArrayInfo(mObject, resId);
             if (rawInfoArray == null) {
                 return null;
             }
+
             final int rawInfoArrayLen = rawInfoArray.length;
             final int infoArrayLen = rawInfoArrayLen / 2;
-            int block;
-            int index;
             final CharSequence[] retArray = new CharSequence[infoArrayLen];
             for (int i = 0, j = 0; i < rawInfoArrayLen; i = i + 2, j++) {
-                block = rawInfoArray[i];
-                index = rawInfoArray[i + 1];
-                retArray[j] = index >= 0 ? mStringBlocks[block].get(index) : null;
+                int cookie = rawInfoArray[i];
+                int index = rawInfoArray[i + 1];
+                retArray[j] = (index >= 0 && cookie > 0)
+                        ? mApkAssets[cookie - 1].getStringFromPool(index) : null;
             }
             return retArray;
         }
     }
 
+    @Nullable int[] getResourceIntArray(@ArrayRes int resId) {
+        synchronized (this) {
+            ensureValidLocked();
+            return nativeGetResourceIntArray(mObject, resId);
+        }
+    }
+
+    /**
+     * Get the attributes for a style resource. These are the &lt;item&gt;
+     * elements in
+     * a &lt;style&gt; resource.
+     * @param resId The resource ID of the style
+     * @return An array of attribute IDs.
+     */
+    @AttrRes int[] getStyleAttributes(@StyleRes int resId) {
+        synchronized (this) {
+            ensureValidLocked();
+            return nativeGetStyleAttributes(mObject, resId);
+        }
+    }
+
     /**
      * Populates {@code outValue} with the data associated with a particular
      * resource identifier for the current configuration. Resolves theme
@@ -279,73 +636,88 @@
      * @return {@code true} if the data was loaded into {@code outValue},
      *         {@code false} otherwise
      */
-    final boolean getThemeValue(long theme, @AnyRes int resId, @NonNull TypedValue outValue,
+    boolean getThemeValue(long theme, @AnyRes int resId, @NonNull TypedValue outValue,
             boolean resolveRefs) {
-        final int block = loadThemeAttributeValue(theme, resId, outValue, resolveRefs);
-        if (block < 0) {
-            return false;
-        }
-
-        // Convert the changing configurations flags populated by native code.
-        outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
-                outValue.changingConfigurations);
-
-        if (outValue.type == TypedValue.TYPE_STRING) {
-            final StringBlock[] blocks = ensureStringBlocks();
-            outValue.string = blocks[block].get(outValue.data);
-        }
-        return true;
-    }
-
-    /**
-     * Ensures the string blocks are loaded.
-     *
-     * @return the string blocks
-     */
-    @NonNull
-    final StringBlock[] ensureStringBlocks() {
+        Preconditions.checkNotNull(outValue, "outValue");
         synchronized (this) {
-            if (mStringBlocks == null) {
-                makeStringBlocks(sSystem.mStringBlocks);
+            ensureValidLocked();
+            final int cookie = nativeThemeGetAttributeValue(mObject, theme, resId, outValue,
+                    resolveRefs);
+            if (cookie <= 0) {
+                return false;
             }
-            return mStringBlocks;
+
+            // Convert the changing configurations flags populated by native code.
+            outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
+                    outValue.changingConfigurations);
+
+            if (outValue.type == TypedValue.TYPE_STRING) {
+                outValue.string = mApkAssets[cookie - 1].getStringFromPool(outValue.data);
+            }
+            return true;
         }
     }
 
-    /*package*/ final void makeStringBlocks(StringBlock[] seed) {
-        final int seedNum = (seed != null) ? seed.length : 0;
-        final int num = getStringBlockCount();
-        mStringBlocks = new StringBlock[num];
-        if (localLOGV) Log.v(TAG, "Making string blocks for " + this
-                + ": " + num);
-        for (int i=0; i<num; i++) {
-            if (i < seedNum) {
-                mStringBlocks[i] = seed[i];
-            } else {
-                mStringBlocks[i] = new StringBlock(getNativeStringBlock(i), true);
-            }
-        }
-    }
-
-    /*package*/ final CharSequence getPooledStringForCookie(int cookie, int id) {
+    void dumpTheme(long theme, int priority, String tag, String prefix) {
         synchronized (this) {
-            // Cookies map to string blocks starting at 1.
-            return mStringBlocks[cookie - 1].get(id);
+            ensureValidLocked();
+            nativeThemeDump(mObject, theme, priority, tag, prefix);
         }
     }
 
+    @Nullable String getResourceName(@AnyRes int resId) {
+        synchronized (this) {
+            ensureValidLocked();
+            return nativeGetResourceName(mObject, resId);
+        }
+    }
+
+    @Nullable String getResourcePackageName(@AnyRes int resId) {
+        synchronized (this) {
+            ensureValidLocked();
+            return nativeGetResourcePackageName(mObject, resId);
+        }
+    }
+
+    @Nullable String getResourceTypeName(@AnyRes int resId) {
+        synchronized (this) {
+            ensureValidLocked();
+            return nativeGetResourceTypeName(mObject, resId);
+        }
+    }
+
+    @Nullable String getResourceEntryName(@AnyRes int resId) {
+        synchronized (this) {
+            ensureValidLocked();
+            return nativeGetResourceEntryName(mObject, resId);
+        }
+    }
+
+    @AnyRes int getResourceIdentifier(@NonNull String name, @Nullable String defType,
+            @Nullable String defPackage) {
+        synchronized (this) {
+            ensureValidLocked();
+            // name is checked in JNI.
+            return nativeGetResourceIdentifier(mObject, name, defType, defPackage);
+        }
+    }
+
+    CharSequence getPooledStringForCookie(int cookie, int id) {
+        // Cookies map to ApkAssets starting at 1.
+        return getApkAssets()[cookie - 1].getStringFromPool(id);
+    }
+
     /**
      * Open an asset using ACCESS_STREAMING mode.  This provides access to
      * files that have been bundled with an application as assets -- that is,
      * files placed in to the "assets" directory.
      * 
-     * @param fileName The name of the asset to open.  This name can be
-     *                 hierarchical.
+     * @param fileName The name of the asset to open.  This name can be hierarchical.
      * 
      * @see #open(String, int)
      * @see #list
      */
-    public final InputStream open(String fileName) throws IOException {
+    public @NonNull InputStream open(@NonNull String fileName) throws IOException {
         return open(fileName, ACCESS_STREAMING);
     }
 
@@ -355,8 +727,7 @@
      * with an application as assets -- that is, files placed in to the
      * "assets" directory.
      * 
-     * @param fileName The name of the asset to open.  This name can be
-     *                 hierarchical.
+     * @param fileName The name of the asset to open.  This name can be hierarchical.
      * @param accessMode Desired access mode for retrieving the data.
      * 
      * @see #ACCESS_UNKNOWN
@@ -366,34 +737,40 @@
      * @see #open(String)
      * @see #list
      */
-    public final InputStream open(String fileName, int accessMode)
-        throws IOException {
+    public @NonNull InputStream open(@NonNull String fileName, int accessMode) throws IOException {
+        Preconditions.checkNotNull(fileName, "fileName");
         synchronized (this) {
-            if (!mOpen) {
-                throw new RuntimeException("Assetmanager has been closed");
+            ensureOpenLocked();
+            final long asset = nativeOpenAsset(mObject, fileName, accessMode);
+            if (asset == 0) {
+                throw new FileNotFoundException("Asset file: " + fileName);
             }
-            long asset = openAsset(fileName, accessMode);
-            if (asset != 0) {
-                AssetInputStream res = new AssetInputStream(asset);
-                incRefsLocked(res.hashCode());
-                return res;
-            }
+            final AssetInputStream assetInputStream = new AssetInputStream(asset);
+            incRefsLocked(assetInputStream.hashCode());
+            return assetInputStream;
         }
-        throw new FileNotFoundException("Asset file: " + fileName);
     }
 
-    public final AssetFileDescriptor openFd(String fileName)
-            throws IOException {
+    /**
+     * Open an uncompressed asset by mmapping it and returning an {@link AssetFileDescriptor}.
+     * This provides access to files that have been bundled with an application as assets -- that
+     * is, files placed in to the "assets" directory.
+     *
+     * The asset must be uncompressed, or an exception will be thrown.
+     *
+     * @param fileName The name of the asset to open.  This name can be hierarchical.
+     * @return An open AssetFileDescriptor.
+     */
+    public @NonNull AssetFileDescriptor openFd(@NonNull String fileName) throws IOException {
+        Preconditions.checkNotNull(fileName, "fileName");
         synchronized (this) {
-            if (!mOpen) {
-                throw new RuntimeException("Assetmanager has been closed");
+            ensureOpenLocked();
+            final ParcelFileDescriptor pfd = nativeOpenAssetFd(mObject, fileName, mOffsets);
+            if (pfd == null) {
+                throw new FileNotFoundException("Asset file: " + fileName);
             }
-            ParcelFileDescriptor pfd = openAssetFd(fileName, mOffsets);
-            if (pfd != null) {
-                return new AssetFileDescriptor(pfd, mOffsets[0], mOffsets[1]);
-            }
+            return new AssetFileDescriptor(pfd, mOffsets[0], mOffsets[1]);
         }
-        throw new FileNotFoundException("Asset file: " + fileName);
     }
 
     /**
@@ -408,90 +785,121 @@
      * 
      * @see #open
      */
-    public native final String[] list(String path)
-        throws IOException;
+    public @Nullable String[] list(@NonNull String path) throws IOException {
+        Preconditions.checkNotNull(path, "path");
+        synchronized (this) {
+            ensureValidLocked();
+            return nativeList(mObject, path);
+        }
+    }
 
     /**
-     * {@hide}
      * Open a non-asset file as an asset using ACCESS_STREAMING mode.  This
      * provides direct access to all of the files included in an application
      * package (not only its assets).  Applications should not normally use
      * this.
-     * 
+     *
+     * @param fileName Name of the asset to retrieve.
+     *
      * @see #open(String)
+     * @hide
      */
-    public final InputStream openNonAsset(String fileName) throws IOException {
+    public @NonNull InputStream openNonAsset(@NonNull String fileName) throws IOException {
         return openNonAsset(0, fileName, ACCESS_STREAMING);
     }
 
     /**
-     * {@hide}
      * Open a non-asset file as an asset using a specific access mode.  This
      * provides direct access to all of the files included in an application
      * package (not only its assets).  Applications should not normally use
      * this.
-     * 
+     *
+     * @param fileName Name of the asset to retrieve.
+     * @param accessMode Desired access mode for retrieving the data.
+     *
+     * @see #ACCESS_UNKNOWN
+     * @see #ACCESS_STREAMING
+     * @see #ACCESS_RANDOM
+     * @see #ACCESS_BUFFER
      * @see #open(String, int)
+     * @hide
      */
-    public final InputStream openNonAsset(String fileName, int accessMode)
-        throws IOException {
+    public @NonNull InputStream openNonAsset(@NonNull String fileName, int accessMode)
+            throws IOException {
         return openNonAsset(0, fileName, accessMode);
     }
 
     /**
-     * {@hide}
      * Open a non-asset in a specified package.  Not for use by applications.
-     * 
+     *
      * @param cookie Identifier of the package to be opened.
      * @param fileName Name of the asset to retrieve.
+     * @hide
      */
-    public final InputStream openNonAsset(int cookie, String fileName)
-        throws IOException {
+    public @NonNull InputStream openNonAsset(int cookie, @NonNull String fileName)
+            throws IOException {
         return openNonAsset(cookie, fileName, ACCESS_STREAMING);
     }
 
     /**
-     * {@hide}
      * Open a non-asset in a specified package.  Not for use by applications.
-     * 
+     *
      * @param cookie Identifier of the package to be opened.
      * @param fileName Name of the asset to retrieve.
      * @param accessMode Desired access mode for retrieving the data.
+     * @hide
      */
-    public final InputStream openNonAsset(int cookie, String fileName, int accessMode)
-        throws IOException {
+    public @NonNull InputStream openNonAsset(int cookie, @NonNull String fileName, int accessMode)
+            throws IOException {
+        Preconditions.checkNotNull(fileName, "fileName");
         synchronized (this) {
-            if (!mOpen) {
-                throw new RuntimeException("Assetmanager has been closed");
+            ensureOpenLocked();
+            final long asset = nativeOpenNonAsset(mObject, cookie, fileName, accessMode);
+            if (asset == 0) {
+                throw new FileNotFoundException("Asset absolute file: " + fileName);
             }
-            long asset = openNonAssetNative(cookie, fileName, accessMode);
-            if (asset != 0) {
-                AssetInputStream res = new AssetInputStream(asset);
-                incRefsLocked(res.hashCode());
-                return res;
-            }
+            final AssetInputStream assetInputStream = new AssetInputStream(asset);
+            incRefsLocked(assetInputStream.hashCode());
+            return assetInputStream;
         }
-        throw new FileNotFoundException("Asset absolute file: " + fileName);
     }
 
-    public final AssetFileDescriptor openNonAssetFd(String fileName)
+    /**
+     * Open a non-asset as an asset by mmapping it and returning an {@link AssetFileDescriptor}.
+     * This provides direct access to all of the files included in an application
+     * package (not only its assets).  Applications should not normally use this.
+     *
+     * The asset must not be compressed, or an exception will be thrown.
+     *
+     * @param fileName Name of the asset to retrieve.
+     */
+    public @NonNull AssetFileDescriptor openNonAssetFd(@NonNull String fileName)
             throws IOException {
         return openNonAssetFd(0, fileName);
     }
-    
-    public final AssetFileDescriptor openNonAssetFd(int cookie,
-            String fileName) throws IOException {
+
+    /**
+     * Open a non-asset as an asset by mmapping it and returning an {@link AssetFileDescriptor}.
+     * This provides direct access to all of the files included in an application
+     * package (not only its assets).  Applications should not normally use this.
+     *
+     * The asset must not be compressed, or an exception will be thrown.
+     *
+     * @param cookie Identifier of the package to be opened.
+     * @param fileName Name of the asset to retrieve.
+     */
+    public @NonNull AssetFileDescriptor openNonAssetFd(int cookie, @NonNull String fileName)
+            throws IOException {
+        Preconditions.checkNotNull(fileName, "fileName");
         synchronized (this) {
-            if (!mOpen) {
-                throw new RuntimeException("Assetmanager has been closed");
+            ensureOpenLocked();
+            final ParcelFileDescriptor pfd =
+                    nativeOpenNonAssetFd(mObject, cookie, fileName, mOffsets);
+            if (pfd == null) {
+                throw new FileNotFoundException("Asset absolute file: " + fileName);
             }
-            ParcelFileDescriptor pfd = openNonAssetFdNative(cookie,
-                    fileName, mOffsets);
-            if (pfd != null) {
-                return new AssetFileDescriptor(pfd, mOffsets[0], mOffsets[1]);
-            }
+            return new AssetFileDescriptor(pfd, mOffsets[0], mOffsets[1]);
         }
-        throw new FileNotFoundException("Asset absolute file: " + fileName);
     }
     
     /**
@@ -499,7 +907,7 @@
      * 
      * @param fileName The name of the file to retrieve.
      */
-    public final XmlResourceParser openXmlResourceParser(String fileName)
+    public @NonNull XmlResourceParser openXmlResourceParser(@NonNull String fileName)
             throws IOException {
         return openXmlResourceParser(0, fileName);
     }
@@ -510,270 +918,265 @@
      * @param cookie Identifier of the package to be opened.
      * @param fileName The name of the file to retrieve.
      */
-    public final XmlResourceParser openXmlResourceParser(int cookie,
-            String fileName) throws IOException {
-        XmlBlock block = openXmlBlockAsset(cookie, fileName);
-        XmlResourceParser rp = block.newParser();
-        block.close();
-        return rp;
+    public @NonNull XmlResourceParser openXmlResourceParser(int cookie, @NonNull String fileName)
+            throws IOException {
+        try (XmlBlock block = openXmlBlockAsset(cookie, fileName)) {
+            XmlResourceParser parser = block.newParser();
+            // If openXmlBlockAsset doesn't throw, it will always return an XmlBlock object with
+            // a valid native pointer, which makes newParser always return non-null. But let's
+            // be paranoid.
+            if (parser == null) {
+                throw new AssertionError("block.newParser() returned a null parser");
+            }
+            return parser;
+        }
     }
 
     /**
-     * {@hide}
-     * Retrieve a non-asset as a compiled XML file.  Not for use by
-     * applications.
+     * Retrieve a non-asset as a compiled XML file.  Not for use by applications.
      * 
      * @param fileName The name of the file to retrieve.
+     * @hide
      */
-    /*package*/ final XmlBlock openXmlBlockAsset(String fileName)
-            throws IOException {
+    @NonNull XmlBlock openXmlBlockAsset(@NonNull String fileName) throws IOException {
         return openXmlBlockAsset(0, fileName);
     }
 
     /**
-     * {@hide}
      * Retrieve a non-asset as a compiled XML file.  Not for use by
      * applications.
      * 
      * @param cookie Identifier of the package to be opened.
      * @param fileName Name of the asset to retrieve.
+     * @hide
      */
-    /*package*/ final XmlBlock openXmlBlockAsset(int cookie, String fileName)
-        throws IOException {
+    @NonNull XmlBlock openXmlBlockAsset(int cookie, @NonNull String fileName) throws IOException {
+        Preconditions.checkNotNull(fileName, "fileName");
         synchronized (this) {
-            if (!mOpen) {
-                throw new RuntimeException("Assetmanager has been closed");
+            ensureOpenLocked();
+            final long xmlBlock = nativeOpenXmlAsset(mObject, cookie, fileName);
+            if (xmlBlock == 0) {
+                throw new FileNotFoundException("Asset XML file: " + fileName);
             }
-            long xmlBlock = openXmlAssetNative(cookie, fileName);
-            if (xmlBlock != 0) {
-                XmlBlock res = new XmlBlock(this, xmlBlock);
-                incRefsLocked(res.hashCode());
-                return res;
-            }
+            final XmlBlock block = new XmlBlock(this, xmlBlock);
+            incRefsLocked(block.hashCode());
+            return block;
         }
-        throw new FileNotFoundException("Asset XML file: " + fileName);
     }
 
-    /*package*/ void xmlBlockGone(int id) {
+    void xmlBlockGone(int id) {
         synchronized (this) {
             decRefsLocked(id);
         }
     }
 
-    /*package*/ final long createTheme() {
+    void applyStyle(long themePtr, @AttrRes int defStyleAttr, @StyleRes int defStyleRes,
+            @Nullable XmlBlock.Parser parser, @NonNull int[] inAttrs, long outValuesAddress,
+            long outIndicesAddress) {
+        Preconditions.checkNotNull(inAttrs, "inAttrs");
         synchronized (this) {
-            if (!mOpen) {
-                throw new RuntimeException("Assetmanager has been closed");
-            }
-            long res = newTheme();
-            incRefsLocked(res);
-            return res;
+            // Need to synchronize on AssetManager because we will be accessing
+            // the native implementation of AssetManager.
+            ensureValidLocked();
+            nativeApplyStyle(mObject, themePtr, defStyleAttr, defStyleRes,
+                    parser != null ? parser.mParseState : 0, inAttrs, outValuesAddress,
+                    outIndicesAddress);
         }
     }
 
-    /*package*/ final void releaseTheme(long theme) {
+    boolean resolveAttrs(long themePtr, @AttrRes int defStyleAttr, @StyleRes int defStyleRes,
+            @Nullable int[] inValues, @NonNull int[] inAttrs, @NonNull int[] outValues,
+            @NonNull int[] outIndices) {
+        Preconditions.checkNotNull(inAttrs, "inAttrs");
+        Preconditions.checkNotNull(outValues, "outValues");
+        Preconditions.checkNotNull(outIndices, "outIndices");
         synchronized (this) {
-            deleteTheme(theme);
-            decRefsLocked(theme);
+            // Need to synchronize on AssetManager because we will be accessing
+            // the native implementation of AssetManager.
+            ensureValidLocked();
+            return nativeResolveAttrs(mObject,
+                    themePtr, defStyleAttr, defStyleRes, inValues, inAttrs, outValues, outIndices);
         }
     }
 
+    boolean retrieveAttributes(@NonNull XmlBlock.Parser parser, @NonNull int[] inAttrs,
+            @NonNull int[] outValues, @NonNull int[] outIndices) {
+        Preconditions.checkNotNull(parser, "parser");
+        Preconditions.checkNotNull(inAttrs, "inAttrs");
+        Preconditions.checkNotNull(outValues, "outValues");
+        Preconditions.checkNotNull(outIndices, "outIndices");
+        synchronized (this) {
+            // Need to synchronize on AssetManager because we will be accessing
+            // the native implementation of AssetManager.
+            ensureValidLocked();
+            return nativeRetrieveAttributes(
+                    mObject, parser.mParseState, inAttrs, outValues, outIndices);
+        }
+    }
+
+    long createTheme() {
+        synchronized (this) {
+            ensureValidLocked();
+            long themePtr = nativeThemeCreate(mObject);
+            incRefsLocked(themePtr);
+            return themePtr;
+        }
+    }
+
+    void releaseTheme(long themePtr) {
+        synchronized (this) {
+            nativeThemeDestroy(themePtr);
+            decRefsLocked(themePtr);
+        }
+    }
+
+    void applyStyleToTheme(long themePtr, @StyleRes int resId, boolean force) {
+        synchronized (this) {
+            // Need to synchronize on AssetManager because we will be accessing
+            // the native implementation of AssetManager.
+            ensureValidLocked();
+            nativeThemeApplyStyle(mObject, themePtr, resId, force);
+        }
+    }
+
+    @Override
     protected void finalize() throws Throwable {
-        try {
-            if (DEBUG_REFS && mNumRefs != 0) {
-                Log.w(TAG, "AssetManager " + this
-                        + " finalized with non-zero refs: " + mNumRefs);
-                if (mRefStacks != null) {
-                    for (RuntimeException e : mRefStacks.values()) {
-                        Log.w(TAG, "Reference from here", e);
-                    }
+        if (DEBUG_REFS && mNumRefs != 0) {
+            Log.w(TAG, "AssetManager " + this + " finalized with non-zero refs: " + mNumRefs);
+            if (mRefStacks != null) {
+                for (RuntimeException e : mRefStacks.values()) {
+                    Log.w(TAG, "Reference from here", e);
                 }
             }
-            destroy();
-        } finally {
-            super.finalize();
+        }
+
+        if (mObject != 0) {
+            nativeDestroy(mObject);
         }
     }
-    
+
+    /* No Locking is needed for AssetInputStream because an AssetInputStream is not-thread
+    safe and it does not rely on AssetManager once it has been created. It completely owns the
+    underlying Asset. */
     public final class AssetInputStream extends InputStream {
+        private long mAssetNativePtr;
+        private long mLength;
+        private long mMarkPos;
+
         /**
          * @hide
          */
         public final int getAssetInt() {
             throw new UnsupportedOperationException();
         }
+
         /**
          * @hide
          */
         public final long getNativeAsset() {
-            return mAsset;
+            return mAssetNativePtr;
         }
-        private AssetInputStream(long asset)
-        {
-            mAsset = asset;
-            mLength = getAssetLength(asset);
+
+        private AssetInputStream(long assetNativePtr) {
+            mAssetNativePtr = assetNativePtr;
+            mLength = nativeAssetGetLength(assetNativePtr);
         }
+
+        @Override
         public final int read() throws IOException {
-            return readAssetChar(mAsset);
+            ensureOpen();
+            return nativeAssetReadChar(mAssetNativePtr);
         }
-        public final boolean markSupported() {
-            return true;
+
+        @Override
+        public final int read(@NonNull byte[] b) throws IOException {
+            ensureOpen();
+            Preconditions.checkNotNull(b, "b");
+            return nativeAssetRead(mAssetNativePtr, b, 0, b.length);
         }
-        public final int available() throws IOException {
-            long len = getAssetRemainingLength(mAsset);
-            return len > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int)len;
+
+        @Override
+        public final int read(@NonNull byte[] b, int off, int len) throws IOException {
+            ensureOpen();
+            Preconditions.checkNotNull(b, "b");
+            return nativeAssetRead(mAssetNativePtr, b, off, len);
         }
-        public final void close() throws IOException {
-            synchronized (AssetManager.this) {
-                if (mAsset != 0) {
-                    destroyAsset(mAsset);
-                    mAsset = 0;
-                    decRefsLocked(hashCode());
-                }
-            }
-        }
-        public final void mark(int readlimit) {
-            mMarkPos = seekAsset(mAsset, 0, 0);
-        }
-        public final void reset() throws IOException {
-            seekAsset(mAsset, mMarkPos, -1);
-        }
-        public final int read(byte[] b) throws IOException {
-            return readAsset(mAsset, b, 0, b.length);
-        }
-        public final int read(byte[] b, int off, int len) throws IOException {
-            return readAsset(mAsset, b, off, len);
-        }
+
+        @Override
         public final long skip(long n) throws IOException {
-            long pos = seekAsset(mAsset, 0, 0);
-            if ((pos+n) > mLength) {
-                n = mLength-pos;
+            ensureOpen();
+            long pos = nativeAssetSeek(mAssetNativePtr, 0, 0);
+            if ((pos + n) > mLength) {
+                n = mLength - pos;
             }
             if (n > 0) {
-                seekAsset(mAsset, n, 0);
+                nativeAssetSeek(mAssetNativePtr, n, 0);
             }
             return n;
         }
 
-        protected void finalize() throws Throwable
-        {
+        @Override
+        public final int available() throws IOException {
+            ensureOpen();
+            final long len = nativeAssetGetRemainingLength(mAssetNativePtr);
+            return len > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) len;
+        }
+
+        @Override
+        public final boolean markSupported() {
+            return true;
+        }
+
+        @Override
+        public final void mark(int readlimit) {
+            ensureOpen();
+            mMarkPos = nativeAssetSeek(mAssetNativePtr, 0, 0);
+        }
+
+        @Override
+        public final void reset() throws IOException {
+            ensureOpen();
+            nativeAssetSeek(mAssetNativePtr, mMarkPos, -1);
+        }
+
+        @Override
+        public final void close() throws IOException {
+            if (mAssetNativePtr != 0) {
+                nativeAssetDestroy(mAssetNativePtr);
+                mAssetNativePtr = 0;
+
+                synchronized (AssetManager.this) {
+                    decRefsLocked(hashCode());
+                }
+            }
+        }
+
+        @Override
+        protected void finalize() throws Throwable {
             close();
         }
 
-        private long mAsset;
-        private long mLength;
-        private long mMarkPos;
-    }
-
-    /**
-     * Add an additional set of assets to the asset manager.  This can be
-     * either a directory or ZIP file.  Not for use by applications.  Returns
-     * the cookie of the added asset, or 0 on failure.
-     * {@hide}
-     */
-    public final int addAssetPath(String path) {
-        return  addAssetPathInternal(path, false);
-    }
-
-    /**
-     * Add an application assets to the asset manager and loading it as shared library.
-     * This can be either a directory or ZIP file.  Not for use by applications.  Returns
-     * the cookie of the added asset, or 0 on failure.
-     * {@hide}
-     */
-    public final int addAssetPathAsSharedLibrary(String path) {
-        return addAssetPathInternal(path, true);
-    }
-
-    private final int addAssetPathInternal(String path, boolean appAsLib) {
-        synchronized (this) {
-            int res = addAssetPathNative(path, appAsLib);
-            makeStringBlocks(mStringBlocks);
-            return res;
+        private void ensureOpen() {
+            if (mAssetNativePtr == 0) {
+                throw new IllegalStateException("AssetInputStream is closed");
+            }
         }
     }
 
-    private native final int addAssetPathNative(String path, boolean appAsLib);
-
-    /**
-     * Add an additional set of assets to the asset manager from an already open
-     * FileDescriptor.  Not for use by applications.
-     * This does not give full AssetManager functionality for these assets,
-     * since the origin of the file is not known for purposes of sharing,
-     * overlay resolution, and other features.  However it does allow you
-     * to do simple access to the contents of the given fd as an apk file.
-     * Performs a dup of the underlying fd, so you must take care of still closing
-     * the FileDescriptor yourself (and can do that whenever you want).
-     * Returns the cookie of the added asset, or 0 on failure.
-     * {@hide}
-     */
-    public int addAssetFd(FileDescriptor fd, String debugPathName) {
-        return addAssetFdInternal(fd, debugPathName, false);
-    }
-
-    private int addAssetFdInternal(FileDescriptor fd, String debugPathName,
-            boolean appAsLib) {
-        synchronized (this) {
-            int res = addAssetFdNative(fd, debugPathName, appAsLib);
-            makeStringBlocks(mStringBlocks);
-            return res;
-        }
-    }
-
-    private native int addAssetFdNative(FileDescriptor fd, String debugPathName,
-            boolean appAsLib);
-
-    /**
-     * Add a set of assets to overlay an already added set of assets.
-     *
-     * This is only intended for application resources. System wide resources
-     * are handled before any Java code is executed.
-     *
-     * {@hide}
-     */
-
-    public final int addOverlayPath(String idmapPath) {
-        synchronized (this) {
-            int res = addOverlayPathNative(idmapPath);
-            makeStringBlocks(mStringBlocks);
-            return res;
-        }
-    }
-
-    /**
-     * See addOverlayPath.
-     *
-     * {@hide}
-     */
-    public native final int addOverlayPathNative(String idmapPath);
-
-    /**
-     * Add multiple sets of assets to the asset manager at once.  See
-     * {@link #addAssetPath(String)} for more information.  Returns array of
-     * cookies for each added asset with 0 indicating failure, or null if
-     * the input array of paths is null.
-     * {@hide}
-     */
-    public final int[] addAssetPaths(String[] paths) {
-        if (paths == null) {
-            return null;
-        }
-
-        int[] cookies = new int[paths.length];
-        for (int i = 0; i < paths.length; i++) {
-            cookies[i] = addAssetPath(paths[i]);
-        }
-
-        return cookies;
-    }
-
     /**
      * Determine whether the state in this asset manager is up-to-date with
      * the files on the filesystem.  If false is returned, you need to
      * instantiate a new AssetManager class to see the new data.
-     * {@hide}
+     * @hide
      */
-    public native final boolean isUpToDate();
+    public boolean isUpToDate() {
+        for (ApkAssets apkAssets : getApkAssets()) {
+            if (!apkAssets.isUpToDate()) {
+                return false;
+            }
+        }
+        return true;
+    }
 
     /**
      * Get the locales that this asset manager contains data for.
@@ -786,7 +1189,12 @@
      * are of the form {@code ll_CC} where {@code ll} is a two letter language code,
      * and {@code CC} is a two letter country code.
      */
-    public native final String[] getLocales();
+    public String[] getLocales() {
+        synchronized (this) {
+            ensureValidLocked();
+            return nativeGetLocales(mObject, false /*excludeSystem*/);
+        }
+    }
 
     /**
      * Same as getLocales(), except that locales that are only provided by the system (i.e. those
@@ -796,132 +1204,58 @@
      * assets support Cherokee and French, getLocales() would return
      * [Cherokee, English, French, German], while getNonSystemLocales() would return
      * [Cherokee, French].
-     * {@hide}
+     * @hide
      */
-    public native final String[] getNonSystemLocales();
-
-    /** {@hide} */
-    public native final Configuration[] getSizeConfigurations();
+    public String[] getNonSystemLocales() {
+        synchronized (this) {
+            ensureValidLocked();
+            return nativeGetLocales(mObject, true /*excludeSystem*/);
+        }
+    }
 
     /**
-     * Change the configuation used when retrieving resources.  Not for use by
+     * @hide
+     */
+    Configuration[] getSizeConfigurations() {
+        synchronized (this) {
+            ensureValidLocked();
+            return nativeGetSizeConfigurations(mObject);
+        }
+    }
+
+    /**
+     * Change the configuration used when retrieving resources.  Not for use by
      * applications.
-     * {@hide}
+     * @hide
      */
-    public native final void setConfiguration(int mcc, int mnc, String locale,
-            int orientation, int touchscreen, int density, int keyboard,
-            int keyboardHidden, int navigation, int screenWidth, int screenHeight,
-            int smallestScreenWidthDp, int screenWidthDp, int screenHeightDp,
-            int screenLayout, int uiMode, int colorMode, int majorVersion);
+    public void setConfiguration(int mcc, int mnc, @Nullable String locale, int orientation,
+            int touchscreen, int density, int keyboard, int keyboardHidden, int navigation,
+            int screenWidth, int screenHeight, int smallestScreenWidthDp, int screenWidthDp,
+            int screenHeightDp, int screenLayout, int uiMode, int colorMode, int majorVersion) {
+        synchronized (this) {
+            ensureValidLocked();
+            nativeSetConfiguration(mObject, mcc, mnc, locale, orientation, touchscreen, density,
+                    keyboard, keyboardHidden, navigation, screenWidth, screenHeight,
+                    smallestScreenWidthDp, screenWidthDp, screenHeightDp, screenLayout, uiMode,
+                    colorMode, majorVersion);
+        }
+    }
 
     /**
-     * Retrieve the resource identifier for the given resource name.
+     * @hide
      */
-    /*package*/ native final int getResourceIdentifier(String name,
-                                                       String defType,
-                                                       String defPackage);
-
-    /*package*/ native final String getResourceName(int resid);
-    /*package*/ native final String getResourcePackageName(int resid);
-    /*package*/ native final String getResourceTypeName(int resid);
-    /*package*/ native final String getResourceEntryName(int resid);
-    
-    private native final long openAsset(String fileName, int accessMode);
-    private final native ParcelFileDescriptor openAssetFd(String fileName,
-            long[] outOffsets) throws IOException;
-    private native final long openNonAssetNative(int cookie, String fileName,
-            int accessMode);
-    private native ParcelFileDescriptor openNonAssetFdNative(int cookie,
-            String fileName, long[] outOffsets) throws IOException;
-    private native final void destroyAsset(long asset);
-    private native final int readAssetChar(long asset);
-    private native final int readAsset(long asset, byte[] b, int off, int len);
-    private native final long seekAsset(long asset, long offset, int whence);
-    private native final long getAssetLength(long asset);
-    private native final long getAssetRemainingLength(long asset);
-
-    /** Returns true if the resource was found, filling in mRetStringBlock and
-     *  mRetData. */
-    private native final int loadResourceValue(int ident, short density, TypedValue outValue,
-            boolean resolve);
-    /** Returns true if the resource was found, filling in mRetStringBlock and
-     *  mRetData. */
-    private native final int loadResourceBagValue(int ident, int bagEntryId, TypedValue outValue,
-                                               boolean resolve);
-    /*package*/ static final int STYLE_NUM_ENTRIES = 6;
-    /*package*/ static final int STYLE_TYPE = 0;
-    /*package*/ static final int STYLE_DATA = 1;
-    /*package*/ static final int STYLE_ASSET_COOKIE = 2;
-    /*package*/ static final int STYLE_RESOURCE_ID = 3;
-
-    /* Offset within typed data array for native changingConfigurations. */
-    static final int STYLE_CHANGING_CONFIGURATIONS = 4;
-
-    /*package*/ static final int STYLE_DENSITY = 5;
-    /*package*/ native static final void applyStyle(long theme,
-            int defStyleAttr, int defStyleRes, long xmlParser,
-            int[] inAttrs, int length, long outValuesAddress, long outIndicesAddress);
-    /*package*/ native static final boolean resolveAttrs(long theme,
-            int defStyleAttr, int defStyleRes, int[] inValues,
-            int[] inAttrs, int[] outValues, int[] outIndices);
-    /*package*/ native final boolean retrieveAttributes(
-            long xmlParser, int[] inAttrs, int[] outValues, int[] outIndices);
-    /*package*/ native final int getArraySize(int resource);
-    /*package*/ native final int retrieveArray(int resource, int[] outValues);
-    private native final int getStringBlockCount();
-    private native final long getNativeStringBlock(int block);
-
-    /**
-     * {@hide}
-     */
-    public native final String getCookieName(int cookie);
-
-    /**
-     * {@hide}
-     */
-    public native final SparseArray<String> getAssignedPackageIdentifiers();
-
-    /**
-     * {@hide}
-     */
-    public native static final int getGlobalAssetCount();
-    
-    /**
-     * {@hide}
-     */
-    public native static final String getAssetAllocations();
-    
-    /**
-     * {@hide}
-     */
-    public native static final int getGlobalAssetManagerCount();
-    
-    private native final long newTheme();
-    private native final void deleteTheme(long theme);
-    /*package*/ native static final void applyThemeStyle(long theme, int styleRes, boolean force);
-    /*package*/ native static final void copyTheme(long dest, long source);
-    /*package*/ native static final void clearTheme(long theme);
-    /*package*/ native static final int loadThemeAttributeValue(long theme, int ident,
-                                                                TypedValue outValue,
-                                                                boolean resolve);
-    /*package*/ native static final void dumpTheme(long theme, int priority, String tag, String prefix);
-    /*package*/ native static final @NativeConfig int getThemeChangingConfigurations(long theme);
-
-    private native final long openXmlAssetNative(int cookie, String fileName);
-
-    private native final String[] getArrayStringResource(int arrayRes);
-    private native final int[] getArrayStringInfo(int arrayRes);
-    /*package*/ native final int[] getArrayIntResource(int arrayRes);
-    /*package*/ native final int[] getStyleAttributes(int themeRes);
-
-    private native final void init(boolean isSystem);
-    private native final void destroy();
+    public SparseArray<String> getAssignedPackageIdentifiers() {
+        synchronized (this) {
+            ensureValidLocked();
+            return nativeGetAssignedPackageIdentifiers(mObject);
+        }
+    }
 
     @GuardedBy("this")
-    private final void incRefsLocked(long id) {
+    private void incRefsLocked(long id) {
         if (DEBUG_REFS) {
             if (mRefStacks == null) {
-                mRefStacks = new HashMap<Long, RuntimeException>();
+                mRefStacks = new HashMap<>();
             }
             RuntimeException ex = new RuntimeException();
             ex.fillInStackTrace();
@@ -931,15 +1265,117 @@
     }
 
     @GuardedBy("this")
-    private final void decRefsLocked(long id) {
+    private void decRefsLocked(long id) {
         if (DEBUG_REFS && mRefStacks != null) {
             mRefStacks.remove(id);
         }
         mNumRefs--;
-        //System.out.println("Dec streams: mNumRefs=" + mNumRefs
-        //                   + " mReleased=" + mReleased);
-        if (mNumRefs == 0) {
-            destroy();
+        if (mNumRefs == 0 && mObject != 0) {
+            nativeDestroy(mObject);
+            mObject = 0;
+            mApkAssets = sEmptyApkAssets;
         }
     }
+
+    // AssetManager setup native methods.
+    private static native long nativeCreate();
+    private static native void nativeDestroy(long ptr);
+    private static native void nativeSetApkAssets(long ptr, @NonNull ApkAssets[] apkAssets,
+            boolean invalidateCaches);
+    private static native void nativeSetConfiguration(long ptr, int mcc, int mnc,
+            @Nullable String locale, int orientation, int touchscreen, int density, int keyboard,
+            int keyboardHidden, int navigation, int screenWidth, int screenHeight,
+            int smallestScreenWidthDp, int screenWidthDp, int screenHeightDp, int screenLayout,
+            int uiMode, int colorMode, int majorVersion);
+    private static native @NonNull SparseArray<String> nativeGetAssignedPackageIdentifiers(
+            long ptr);
+
+    // File native methods.
+    private static native @Nullable String[] nativeList(long ptr, @NonNull String path)
+            throws IOException;
+    private static native long nativeOpenAsset(long ptr, @NonNull String fileName, int accessMode);
+    private static native @Nullable ParcelFileDescriptor nativeOpenAssetFd(long ptr,
+            @NonNull String fileName, long[] outOffsets) throws IOException;
+    private static native long nativeOpenNonAsset(long ptr, int cookie, @NonNull String fileName,
+            int accessMode);
+    private static native @Nullable ParcelFileDescriptor nativeOpenNonAssetFd(long ptr, int cookie,
+            @NonNull String fileName, @NonNull long[] outOffsets) throws IOException;
+    private static native long nativeOpenXmlAsset(long ptr, int cookie, @NonNull String fileName);
+
+    // Primitive resource native methods.
+    private static native int nativeGetResourceValue(long ptr, @AnyRes int resId, short density,
+            @NonNull TypedValue outValue, boolean resolveReferences);
+    private static native int nativeGetResourceBagValue(long ptr, @AnyRes int resId, int bagEntryId,
+            @NonNull TypedValue outValue);
+
+    private static native @Nullable @AttrRes int[] nativeGetStyleAttributes(long ptr,
+            @StyleRes int resId);
+    private static native @Nullable String[] nativeGetResourceStringArray(long ptr,
+            @ArrayRes int resId);
+    private static native @Nullable int[] nativeGetResourceStringArrayInfo(long ptr,
+            @ArrayRes int resId);
+    private static native @Nullable int[] nativeGetResourceIntArray(long ptr, @ArrayRes int resId);
+    private static native int nativeGetResourceArraySize(long ptr, @ArrayRes int resId);
+    private static native int nativeGetResourceArray(long ptr, @ArrayRes int resId,
+            @NonNull int[] outValues);
+
+    // Resource name/ID native methods.
+    private static native @AnyRes int nativeGetResourceIdentifier(long ptr, @NonNull String name,
+            @Nullable String defType, @Nullable String defPackage);
+    private static native @Nullable String nativeGetResourceName(long ptr, @AnyRes int resid);
+    private static native @Nullable String nativeGetResourcePackageName(long ptr,
+            @AnyRes int resid);
+    private static native @Nullable String nativeGetResourceTypeName(long ptr, @AnyRes int resid);
+    private static native @Nullable String nativeGetResourceEntryName(long ptr, @AnyRes int resid);
+    private static native @Nullable String[] nativeGetLocales(long ptr, boolean excludeSystem);
+    private static native @Nullable Configuration[] nativeGetSizeConfigurations(long ptr);
+
+    // Style attribute retrieval native methods.
+    private static native void nativeApplyStyle(long ptr, long themePtr, @AttrRes int defStyleAttr,
+            @StyleRes int defStyleRes, long xmlParserPtr, @NonNull int[] inAttrs,
+            long outValuesAddress, long outIndicesAddress);
+    private static native boolean nativeResolveAttrs(long ptr, long themePtr,
+            @AttrRes int defStyleAttr, @StyleRes int defStyleRes, @Nullable int[] inValues,
+            @NonNull int[] inAttrs, @NonNull int[] outValues, @NonNull int[] outIndices);
+    private static native boolean nativeRetrieveAttributes(long ptr, long xmlParserPtr,
+            @NonNull int[] inAttrs, @NonNull int[] outValues, @NonNull int[] outIndices);
+
+    // Theme related native methods
+    private static native long nativeThemeCreate(long ptr);
+    private static native void nativeThemeDestroy(long themePtr);
+    private static native void nativeThemeApplyStyle(long ptr, long themePtr, @StyleRes int resId,
+            boolean force);
+    static native void nativeThemeCopy(long destThemePtr, long sourceThemePtr);
+    static native void nativeThemeClear(long themePtr);
+    private static native int nativeThemeGetAttributeValue(long ptr, long themePtr,
+            @AttrRes int resId, @NonNull TypedValue outValue, boolean resolve);
+    private static native void nativeThemeDump(long ptr, long themePtr, int priority, String tag,
+            String prefix);
+    static native @NativeConfig int nativeThemeGetChangingConfigurations(long themePtr);
+
+    // AssetInputStream related native methods.
+    private static native void nativeAssetDestroy(long assetPtr);
+    private static native int nativeAssetReadChar(long assetPtr);
+    private static native int nativeAssetRead(long assetPtr, byte[] b, int off, int len);
+    private static native long nativeAssetSeek(long assetPtr, long offset, int whence);
+    private static native long nativeAssetGetLength(long assetPtr);
+    private static native long nativeAssetGetRemainingLength(long assetPtr);
+
+    private static native void nativeVerifySystemIdmaps();
+
+    // Global debug native methods.
+    /**
+     * @hide
+     */
+    public static native int getGlobalAssetCount();
+
+    /**
+     * @hide
+     */
+    public static native String getAssetAllocations();
+
+    /**
+     * @hide
+     */
+    public static native int getGlobalAssetManagerCount();
 }
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index ad85e71..d813382 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -590,7 +590,7 @@
      */
     @NonNull
     public int[] getIntArray(@ArrayRes int id) throws NotFoundException {
-        int[] res = mResourcesImpl.getAssets().getArrayIntResource(id);
+        int[] res = mResourcesImpl.getAssets().getResourceIntArray(id);
         if (res != null) {
             return res;
         }
@@ -613,13 +613,13 @@
     @NonNull
     public TypedArray obtainTypedArray(@ArrayRes int id) throws NotFoundException {
         final ResourcesImpl impl = mResourcesImpl;
-        int len = impl.getAssets().getArraySize(id);
+        int len = impl.getAssets().getResourceArraySize(id);
         if (len < 0) {
             throw new NotFoundException("Array resource ID #0x" + Integer.toHexString(id));
         }
         
         TypedArray array = TypedArray.obtain(this, len);
-        array.mLength = impl.getAssets().retrieveArray(id, array.mData);
+        array.mLength = impl.getAssets().getResourceArray(id, array.mData);
         array.mIndices[0] = 0;
         
         return array;
@@ -1794,8 +1794,7 @@
         // out the attributes from the XML file (applying type information
         // contained in the resources and such).
         XmlBlock.Parser parser = (XmlBlock.Parser)set;
-        mResourcesImpl.getAssets().retrieveAttributes(parser.mParseState, attrs,
-                array.mData, array.mIndices);
+        mResourcesImpl.getAssets().retrieveAttributes(parser, attrs, array.mData, array.mIndices);
 
         array.mXml = parser;
 
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 424fa83..157910a 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -170,7 +170,6 @@
         mDisplayAdjustments = displayAdjustments;
         mConfiguration.setToDefaults();
         updateConfiguration(config, metrics, displayAdjustments.getCompatibilityInfo());
-        mAssets.ensureStringBlocks();
     }
 
     public DisplayAdjustments getDisplayAdjustments() {
@@ -1300,8 +1299,7 @@
 
         void applyStyle(int resId, boolean force) {
             synchronized (mKey) {
-                AssetManager.applyThemeStyle(mTheme, resId, force);
-
+                mAssets.applyStyleToTheme(mTheme, resId, force);
                 mThemeResId = resId;
                 mKey.append(resId, force);
             }
@@ -1310,7 +1308,7 @@
         void setTo(ThemeImpl other) {
             synchronized (mKey) {
                 synchronized (other.mKey) {
-                    AssetManager.copyTheme(mTheme, other.mTheme);
+                    AssetManager.nativeThemeCopy(mTheme, other.mTheme);
 
                     mThemeResId = other.mThemeResId;
                     mKey.setTo(other.getKey());
@@ -1333,12 +1331,10 @@
                 // out the attributes from the XML file (applying type information
                 // contained in the resources and such).
                 final XmlBlock.Parser parser = (XmlBlock.Parser) set;
-                AssetManager.applyStyle(mTheme, defStyleAttr, defStyleRes,
-                        parser != null ? parser.mParseState : 0,
-                        attrs, attrs.length, array.mDataAddress, array.mIndicesAddress);
+                mAssets.applyStyle(mTheme, defStyleAttr, defStyleRes, parser, attrs,
+                        array.mDataAddress, array.mIndicesAddress);
                 array.mTheme = wrapper;
                 array.mXml = parser;
-
                 return array;
             }
         }
@@ -1355,7 +1351,7 @@
                 }
 
                 final TypedArray array = TypedArray.obtain(wrapper.getResources(), len);
-                AssetManager.resolveAttrs(mTheme, 0, 0, values, attrs, array.mData, array.mIndices);
+                mAssets.resolveAttrs(mTheme, 0, 0, values, attrs, array.mData, array.mIndices);
                 array.mTheme = wrapper;
                 array.mXml = null;
                 return array;
@@ -1375,14 +1371,14 @@
         @Config int getChangingConfigurations() {
             synchronized (mKey) {
                 final @NativeConfig int nativeChangingConfig =
-                        AssetManager.getThemeChangingConfigurations(mTheme);
+                        AssetManager.nativeThemeGetChangingConfigurations(mTheme);
                 return ActivityInfo.activityInfoConfigNativeToJava(nativeChangingConfig);
             }
         }
 
         public void dump(int priority, String tag, String prefix) {
             synchronized (mKey) {
-                AssetManager.dumpTheme(mTheme, priority, tag, prefix);
+                mAssets.dumpTheme(mTheme, priority, tag, prefix);
             }
         }
 
@@ -1411,13 +1407,13 @@
          */
         void rebase() {
             synchronized (mKey) {
-                AssetManager.clearTheme(mTheme);
+                AssetManager.nativeThemeClear(mTheme);
 
                 // Reapply the same styles in the same order.
                 for (int i = 0; i < mKey.mCount; i++) {
                     final int resId = mKey.mResId[i];
                     final boolean force = mKey.mForce[i];
-                    AssetManager.applyThemeStyle(mTheme, resId, force);
+                    mAssets.applyStyleToTheme(mTheme, resId, force);
                 }
             }
         }
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index f33c751..cbb3c6d 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -61,6 +61,15 @@
         return attrs;
     }
 
+    // STYLE_ prefixed constants are offsets within the typed data array.
+    static final int STYLE_NUM_ENTRIES = 6;
+    static final int STYLE_TYPE = 0;
+    static final int STYLE_DATA = 1;
+    static final int STYLE_ASSET_COOKIE = 2;
+    static final int STYLE_RESOURCE_ID = 3;
+    static final int STYLE_CHANGING_CONFIGURATIONS = 4;
+    static final int STYLE_DENSITY = 5;
+
     private final Resources mResources;
     private DisplayMetrics mMetrics;
     private AssetManager mAssets;
@@ -78,7 +87,7 @@
 
     private void resize(int len) {
         mLength = len;
-        final int dataLen = len * AssetManager.STYLE_NUM_ENTRIES;
+        final int dataLen = len * STYLE_NUM_ENTRIES;
         final int indicesLen = len + 1;
         final VMRuntime runtime = VMRuntime.getRuntime();
         if (mDataAddress == 0 || mData.length < dataLen) {
@@ -166,9 +175,9 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        index *= AssetManager.STYLE_NUM_ENTRIES;
+        index *= STYLE_NUM_ENTRIES;
         final int[] data = mData;
-        final int type = data[index+AssetManager.STYLE_TYPE];
+        final int type = data[index + STYLE_TYPE];
         if (type == TypedValue.TYPE_NULL) {
             return null;
         } else if (type == TypedValue.TYPE_STRING) {
@@ -203,9 +212,9 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        index *= AssetManager.STYLE_NUM_ENTRIES;
+        index *= STYLE_NUM_ENTRIES;
         final int[] data = mData;
-        final int type = data[index+AssetManager.STYLE_TYPE];
+        final int type = data[index + STYLE_TYPE];
         if (type == TypedValue.TYPE_NULL) {
             return null;
         } else if (type == TypedValue.TYPE_STRING) {
@@ -242,14 +251,13 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        index *= AssetManager.STYLE_NUM_ENTRIES;
+        index *= STYLE_NUM_ENTRIES;
         final int[] data = mData;
-        final int type = data[index+AssetManager.STYLE_TYPE];
+        final int type = data[index + STYLE_TYPE];
         if (type == TypedValue.TYPE_STRING) {
-            final int cookie = data[index+AssetManager.STYLE_ASSET_COOKIE];
+            final int cookie = data[index + STYLE_ASSET_COOKIE];
             if (cookie < 0) {
-                return mXml.getPooledString(
-                    data[index+AssetManager.STYLE_DATA]).toString();
+                return mXml.getPooledString(data[index + STYLE_DATA]).toString();
             }
         }
         return null;
@@ -274,11 +282,11 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        index *= AssetManager.STYLE_NUM_ENTRIES;
+        index *= STYLE_NUM_ENTRIES;
         final int[] data = mData;
-        final int type = data[index+AssetManager.STYLE_TYPE];
+        final int type = data[index + STYLE_TYPE];
         final @Config int changingConfigs = ActivityInfo.activityInfoConfigNativeToJava(
-                data[index + AssetManager.STYLE_CHANGING_CONFIGURATIONS]);
+                data[index + STYLE_CHANGING_CONFIGURATIONS]);
         if ((changingConfigs & ~allowedChangingConfigs) != 0) {
             return null;
         }
@@ -320,14 +328,14 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        index *= AssetManager.STYLE_NUM_ENTRIES;
+        index *= STYLE_NUM_ENTRIES;
         final int[] data = mData;
-        final int type = data[index+AssetManager.STYLE_TYPE];
+        final int type = data[index + STYLE_TYPE];
         if (type == TypedValue.TYPE_NULL) {
             return defValue;
         } else if (type >= TypedValue.TYPE_FIRST_INT
                 && type <= TypedValue.TYPE_LAST_INT) {
-            return data[index+AssetManager.STYLE_DATA] != 0;
+            return data[index + STYLE_DATA] != 0;
         }
 
         final TypedValue v = mValue;
@@ -359,14 +367,14 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        index *= AssetManager.STYLE_NUM_ENTRIES;
+        index *= STYLE_NUM_ENTRIES;
         final int[] data = mData;
-        final int type = data[index+AssetManager.STYLE_TYPE];
+        final int type = data[index + STYLE_TYPE];
         if (type == TypedValue.TYPE_NULL) {
             return defValue;
         } else if (type >= TypedValue.TYPE_FIRST_INT
                 && type <= TypedValue.TYPE_LAST_INT) {
-            return data[index+AssetManager.STYLE_DATA];
+            return data[index + STYLE_DATA];
         }
 
         final TypedValue v = mValue;
@@ -396,16 +404,16 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        index *= AssetManager.STYLE_NUM_ENTRIES;
+        index *= STYLE_NUM_ENTRIES;
         final int[] data = mData;
-        final int type = data[index+AssetManager.STYLE_TYPE];
+        final int type = data[index + STYLE_TYPE];
         if (type == TypedValue.TYPE_NULL) {
             return defValue;
         } else if (type == TypedValue.TYPE_FLOAT) {
-            return Float.intBitsToFloat(data[index+AssetManager.STYLE_DATA]);
+            return Float.intBitsToFloat(data[index + STYLE_DATA]);
         } else if (type >= TypedValue.TYPE_FIRST_INT
                 && type <= TypedValue.TYPE_LAST_INT) {
-            return data[index+AssetManager.STYLE_DATA];
+            return data[index + STYLE_DATA];
         }
 
         final TypedValue v = mValue;
@@ -446,15 +454,15 @@
         }
 
         final int attrIndex = index;
-        index *= AssetManager.STYLE_NUM_ENTRIES;
+        index *= STYLE_NUM_ENTRIES;
 
         final int[] data = mData;
-        final int type = data[index+AssetManager.STYLE_TYPE];
+        final int type = data[index + STYLE_TYPE];
         if (type == TypedValue.TYPE_NULL) {
             return defValue;
         } else if (type >= TypedValue.TYPE_FIRST_INT
                 && type <= TypedValue.TYPE_LAST_INT) {
-            return data[index+AssetManager.STYLE_DATA];
+            return data[index + STYLE_DATA];
         } else if (type == TypedValue.TYPE_STRING) {
             final TypedValue value = mValue;
             if (getValueAt(index, value)) {
@@ -498,7 +506,7 @@
         }
 
         final TypedValue value = mValue;
-        if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
+        if (getValueAt(index * STYLE_NUM_ENTRIES, value)) {
             if (value.type == TypedValue.TYPE_ATTRIBUTE) {
                 throw new UnsupportedOperationException(
                         "Failed to resolve attribute at index " + index + ": " + value);
@@ -533,7 +541,7 @@
         }
 
         final TypedValue value = mValue;
-        if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
+        if (getValueAt(index * STYLE_NUM_ENTRIES, value)) {
             if (value.type == TypedValue.TYPE_ATTRIBUTE) {
                 throw new UnsupportedOperationException(
                         "Failed to resolve attribute at index " + index + ": " + value);
@@ -564,15 +572,15 @@
         }
 
         final int attrIndex = index;
-        index *= AssetManager.STYLE_NUM_ENTRIES;
+        index *= STYLE_NUM_ENTRIES;
 
         final int[] data = mData;
-        final int type = data[index+AssetManager.STYLE_TYPE];
+        final int type = data[index + STYLE_TYPE];
         if (type == TypedValue.TYPE_NULL) {
             return defValue;
         } else if (type >= TypedValue.TYPE_FIRST_INT
                 && type <= TypedValue.TYPE_LAST_INT) {
-            return data[index+AssetManager.STYLE_DATA];
+            return data[index + STYLE_DATA];
         } else if (type == TypedValue.TYPE_ATTRIBUTE) {
             final TypedValue value = mValue;
             getValueAt(index, value);
@@ -612,15 +620,14 @@
         }
 
         final int attrIndex = index;
-        index *= AssetManager.STYLE_NUM_ENTRIES;
+        index *= STYLE_NUM_ENTRIES;
 
         final int[] data = mData;
-        final int type = data[index+AssetManager.STYLE_TYPE];
+        final int type = data[index + STYLE_TYPE];
         if (type == TypedValue.TYPE_NULL) {
             return defValue;
         } else if (type == TypedValue.TYPE_DIMENSION) {
-            return TypedValue.complexToDimension(
-                    data[index + AssetManager.STYLE_DATA], mMetrics);
+            return TypedValue.complexToDimension(data[index + STYLE_DATA], mMetrics);
         } else if (type == TypedValue.TYPE_ATTRIBUTE) {
             final TypedValue value = mValue;
             getValueAt(index, value);
@@ -661,15 +668,14 @@
         }
 
         final int attrIndex = index;
-        index *= AssetManager.STYLE_NUM_ENTRIES;
+        index *= STYLE_NUM_ENTRIES;
 
         final int[] data = mData;
-        final int type = data[index+AssetManager.STYLE_TYPE];
+        final int type = data[index + STYLE_TYPE];
         if (type == TypedValue.TYPE_NULL) {
             return defValue;
         } else if (type == TypedValue.TYPE_DIMENSION) {
-            return TypedValue.complexToDimensionPixelOffset(
-                    data[index + AssetManager.STYLE_DATA], mMetrics);
+            return TypedValue.complexToDimensionPixelOffset(data[index + STYLE_DATA], mMetrics);
         } else if (type == TypedValue.TYPE_ATTRIBUTE) {
             final TypedValue value = mValue;
             getValueAt(index, value);
@@ -711,15 +717,14 @@
         }
 
         final int attrIndex = index;
-        index *= AssetManager.STYLE_NUM_ENTRIES;
+        index *= STYLE_NUM_ENTRIES;
 
         final int[] data = mData;
-        final int type = data[index+AssetManager.STYLE_TYPE];
+        final int type = data[index + STYLE_TYPE];
         if (type == TypedValue.TYPE_NULL) {
             return defValue;
         } else if (type == TypedValue.TYPE_DIMENSION) {
-            return TypedValue.complexToDimensionPixelSize(
-                data[index+AssetManager.STYLE_DATA], mMetrics);
+            return TypedValue.complexToDimensionPixelSize(data[index + STYLE_DATA], mMetrics);
         } else if (type == TypedValue.TYPE_ATTRIBUTE) {
             final TypedValue value = mValue;
             getValueAt(index, value);
@@ -755,16 +760,15 @@
         }
 
         final int attrIndex = index;
-        index *= AssetManager.STYLE_NUM_ENTRIES;
+        index *= STYLE_NUM_ENTRIES;
 
         final int[] data = mData;
-        final int type = data[index+AssetManager.STYLE_TYPE];
+        final int type = data[index + STYLE_TYPE];
         if (type >= TypedValue.TYPE_FIRST_INT
                 && type <= TypedValue.TYPE_LAST_INT) {
-            return data[index+AssetManager.STYLE_DATA];
+            return data[index + STYLE_DATA];
         } else if (type == TypedValue.TYPE_DIMENSION) {
-            return TypedValue.complexToDimensionPixelSize(
-                data[index+AssetManager.STYLE_DATA], mMetrics);
+            return TypedValue.complexToDimensionPixelSize(data[index + STYLE_DATA], mMetrics);
         } else if (type == TypedValue.TYPE_ATTRIBUTE) {
             final TypedValue value = mValue;
             getValueAt(index, value);
@@ -795,15 +799,14 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        index *= AssetManager.STYLE_NUM_ENTRIES;
+        index *= STYLE_NUM_ENTRIES;
         final int[] data = mData;
-        final int type = data[index+AssetManager.STYLE_TYPE];
+        final int type = data[index + STYLE_TYPE];
         if (type >= TypedValue.TYPE_FIRST_INT
                 && type <= TypedValue.TYPE_LAST_INT) {
-            return data[index+AssetManager.STYLE_DATA];
+            return data[index + STYLE_DATA];
         } else if (type == TypedValue.TYPE_DIMENSION) {
-            return TypedValue.complexToDimensionPixelSize(
-                    data[index + AssetManager.STYLE_DATA], mMetrics);
+            return TypedValue.complexToDimensionPixelSize(data[index + STYLE_DATA], mMetrics);
         }
 
         return defValue;
@@ -833,15 +836,14 @@
         }
 
         final int attrIndex = index;
-        index *= AssetManager.STYLE_NUM_ENTRIES;
+        index *= STYLE_NUM_ENTRIES;
 
         final int[] data = mData;
-        final int type = data[index+AssetManager.STYLE_TYPE];
+        final int type = data[index + STYLE_TYPE];
         if (type == TypedValue.TYPE_NULL) {
             return defValue;
         } else if (type == TypedValue.TYPE_FRACTION) {
-            return TypedValue.complexToFraction(
-                data[index+AssetManager.STYLE_DATA], base, pbase);
+            return TypedValue.complexToFraction(data[index + STYLE_DATA], base, pbase);
         } else if (type == TypedValue.TYPE_ATTRIBUTE) {
             final TypedValue value = mValue;
             getValueAt(index, value);
@@ -874,10 +876,10 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        index *= AssetManager.STYLE_NUM_ENTRIES;
+        index *= STYLE_NUM_ENTRIES;
         final int[] data = mData;
-        if (data[index+AssetManager.STYLE_TYPE] != TypedValue.TYPE_NULL) {
-            final int resid = data[index+AssetManager.STYLE_RESOURCE_ID];
+        if (data[index + STYLE_TYPE] != TypedValue.TYPE_NULL) {
+            final int resid = data[index + STYLE_RESOURCE_ID];
             if (resid != 0) {
                 return resid;
             }
@@ -902,10 +904,10 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        index *= AssetManager.STYLE_NUM_ENTRIES;
+        index *= STYLE_NUM_ENTRIES;
         final int[] data = mData;
-        if (data[index + AssetManager.STYLE_TYPE] == TypedValue.TYPE_ATTRIBUTE) {
-            return data[index + AssetManager.STYLE_DATA];
+        if (data[index + STYLE_TYPE] == TypedValue.TYPE_ATTRIBUTE) {
+            return data[index + STYLE_DATA];
         }
         return defValue;
     }
@@ -939,7 +941,7 @@
         }
 
         final TypedValue value = mValue;
-        if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
+        if (getValueAt(index * STYLE_NUM_ENTRIES, value)) {
             if (value.type == TypedValue.TYPE_ATTRIBUTE) {
                 throw new UnsupportedOperationException(
                         "Failed to resolve attribute at index " + index + ": " + value);
@@ -975,7 +977,7 @@
         }
 
         final TypedValue value = mValue;
-        if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
+        if (getValueAt(index * STYLE_NUM_ENTRIES, value)) {
             if (value.type == TypedValue.TYPE_ATTRIBUTE) {
                 throw new UnsupportedOperationException(
                         "Failed to resolve attribute at index " + index + ": " + value);
@@ -1006,7 +1008,7 @@
         }
 
         final TypedValue value = mValue;
-        if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
+        if (getValueAt(index * STYLE_NUM_ENTRIES, value)) {
             return mResources.getTextArray(value.resourceId);
         }
         return null;
@@ -1027,7 +1029,7 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        return getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, outValue);
+        return getValueAt(index * STYLE_NUM_ENTRIES, outValue);
     }
 
     /**
@@ -1043,8 +1045,8 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        index *= AssetManager.STYLE_NUM_ENTRIES;
-        return mData[index + AssetManager.STYLE_TYPE];
+        index *= STYLE_NUM_ENTRIES;
+        return mData[index + STYLE_TYPE];
     }
 
     /**
@@ -1063,9 +1065,9 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        index *= AssetManager.STYLE_NUM_ENTRIES;
+        index *= STYLE_NUM_ENTRIES;
         final int[] data = mData;
-        final int type = data[index+AssetManager.STYLE_TYPE];
+        final int type = data[index + STYLE_TYPE];
         return type != TypedValue.TYPE_NULL;
     }
 
@@ -1084,11 +1086,11 @@
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        index *= AssetManager.STYLE_NUM_ENTRIES;
+        index *= STYLE_NUM_ENTRIES;
         final int[] data = mData;
-        final int type = data[index+AssetManager.STYLE_TYPE];
+        final int type = data[index + STYLE_TYPE];
         return type != TypedValue.TYPE_NULL
-                || data[index+AssetManager.STYLE_DATA] == TypedValue.DATA_NULL_EMPTY;
+                || data[index + STYLE_DATA] == TypedValue.DATA_NULL_EMPTY;
     }
 
     /**
@@ -1109,7 +1111,7 @@
         }
 
         final TypedValue value = mValue;
-        if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
+        if (getValueAt(index * STYLE_NUM_ENTRIES, value)) {
             return value;
         }
         return null;
@@ -1181,16 +1183,16 @@
         final int[] data = mData;
         final int N = length();
         for (int i = 0; i < N; i++) {
-            final int index = i * AssetManager.STYLE_NUM_ENTRIES;
-            if (data[index + AssetManager.STYLE_TYPE] != TypedValue.TYPE_ATTRIBUTE) {
+            final int index = i * STYLE_NUM_ENTRIES;
+            if (data[index + STYLE_TYPE] != TypedValue.TYPE_ATTRIBUTE) {
                 // Not an attribute, ignore.
                 continue;
             }
 
             // Null the entry so that we can safely call getZzz().
-            data[index + AssetManager.STYLE_TYPE] = TypedValue.TYPE_NULL;
+            data[index + STYLE_TYPE] = TypedValue.TYPE_NULL;
 
-            final int attr = data[index + AssetManager.STYLE_DATA];
+            final int attr = data[index + STYLE_DATA];
             if (attr == 0) {
                 // Useless data, ignore.
                 continue;
@@ -1231,45 +1233,44 @@
         final int[] data = mData;
         final int N = length();
         for (int i = 0; i < N; i++) {
-            final int index = i * AssetManager.STYLE_NUM_ENTRIES;
-            final int type = data[index + AssetManager.STYLE_TYPE];
+            final int index = i * STYLE_NUM_ENTRIES;
+            final int type = data[index + STYLE_TYPE];
             if (type == TypedValue.TYPE_NULL) {
                 continue;
             }
             changingConfig |= ActivityInfo.activityInfoConfigNativeToJava(
-                    data[index + AssetManager.STYLE_CHANGING_CONFIGURATIONS]);
+                    data[index + STYLE_CHANGING_CONFIGURATIONS]);
         }
         return changingConfig;
     }
 
     private boolean getValueAt(int index, TypedValue outValue) {
         final int[] data = mData;
-        final int type = data[index+AssetManager.STYLE_TYPE];
+        final int type = data[index + STYLE_TYPE];
         if (type == TypedValue.TYPE_NULL) {
             return false;
         }
         outValue.type = type;
-        outValue.data = data[index+AssetManager.STYLE_DATA];
-        outValue.assetCookie = data[index+AssetManager.STYLE_ASSET_COOKIE];
-        outValue.resourceId = data[index+AssetManager.STYLE_RESOURCE_ID];
+        outValue.data = data[index + STYLE_DATA];
+        outValue.assetCookie = data[index + STYLE_ASSET_COOKIE];
+        outValue.resourceId = data[index + STYLE_RESOURCE_ID];
         outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
-                data[index + AssetManager.STYLE_CHANGING_CONFIGURATIONS]);
-        outValue.density = data[index+AssetManager.STYLE_DENSITY];
+                data[index + STYLE_CHANGING_CONFIGURATIONS]);
+        outValue.density = data[index + STYLE_DENSITY];
         outValue.string = (type == TypedValue.TYPE_STRING) ? loadStringValueAt(index) : null;
         return true;
     }
 
     private CharSequence loadStringValueAt(int index) {
         final int[] data = mData;
-        final int cookie = data[index+AssetManager.STYLE_ASSET_COOKIE];
+        final int cookie = data[index + STYLE_ASSET_COOKIE];
         if (cookie < 0) {
             if (mXml != null) {
-                return mXml.getPooledString(
-                    data[index+AssetManager.STYLE_DATA]);
+                return mXml.getPooledString(data[index + STYLE_DATA]);
             }
             return null;
         }
-        return mAssets.getPooledStringForCookie(cookie, data[index+AssetManager.STYLE_DATA]);
+        return mAssets.getPooledStringForCookie(cookie, data[index + STYLE_DATA]);
     }
 
     /** @hide */
diff --git a/core/java/android/content/res/XmlBlock.java b/core/java/android/content/res/XmlBlock.java
index e6b95741..d4ccffb 100644
--- a/core/java/android/content/res/XmlBlock.java
+++ b/core/java/android/content/res/XmlBlock.java
@@ -16,6 +16,7 @@
 
 package android.content.res;
 
+import android.annotation.Nullable;
 import android.util.TypedValue;
 
 import com.android.internal.util.XmlUtils;
@@ -33,7 +34,7 @@
  * 
  * {@hide}
  */
-final class XmlBlock {
+final class XmlBlock implements AutoCloseable {
     private static final boolean DEBUG=false;
 
     public XmlBlock(byte[] data) {
@@ -48,6 +49,7 @@
         mStrings = new StringBlock(nativeGetStringBlock(mNative), false);
     }
 
+    @Override
     public void close() {
         synchronized (this) {
             if (mOpen) {
@@ -478,13 +480,13 @@
      *  are doing!  The given native object must exist for the entire lifetime
      *  of this newly creating XmlBlock.
      */
-    XmlBlock(AssetManager assets, long xmlBlock) {
+    XmlBlock(@Nullable AssetManager assets, long xmlBlock) {
         mAssets = assets;
         mNative = xmlBlock;
         mStrings = new StringBlock(nativeGetStringBlock(xmlBlock), false);
     }
 
-    private final AssetManager mAssets;
+    private @Nullable final AssetManager mAssets;
     private final long mNative;
     /*package*/ final StringBlock mStrings;
     private boolean mOpen = true;
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index ada7ebf..98901a1 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -1457,7 +1457,8 @@
      * is used, all non-zero weights will have the same effect. A region with 0 weight is
      * ignored.</p>
      * <p>If all regions have 0 weight, then no specific metering area needs to be used by the
-     * camera device.</p>
+     * camera device. The capture result will either be a zero weight region as well, or
+     * the region selected by the camera device as the focus area of interest.</p>
      * <p>If the metering region is outside the used {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} returned in
      * capture result metadata, the camera device will ignore the sections outside the crop
      * region and output only the intersection rectangle as the metering region in the result
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 8c2f8c1..e14dfa8 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -1156,7 +1156,8 @@
      * is used, all non-zero weights will have the same effect. A region with 0 weight is
      * ignored.</p>
      * <p>If all regions have 0 weight, then no specific metering area needs to be used by the
-     * camera device.</p>
+     * camera device. The capture result will either be a zero weight region as well, or
+     * the region selected by the camera device as the focus area of interest.</p>
      * <p>If the metering region is outside the used {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} returned in
      * capture result metadata, the camera device will ignore the sections outside the crop
      * region and output only the intersection rectangle as the metering region in the result
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 17b46c6..ef58f94 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -17,6 +17,7 @@
 package android.net;
 
 import android.annotation.IntDef;
+import android.annotation.SystemApi;
 import android.net.ConnectivityManager.NetworkCallback;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -69,6 +70,7 @@
             mSignalStrength = nc.mSignalStrength;
             mUids = nc.mUids;
             mEstablishingVpnAppUid = nc.mEstablishingVpnAppUid;
+            mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities;
         }
     }
 
@@ -78,7 +80,7 @@
      * @hide
      */
     public void clearAll() {
-        mNetworkCapabilities = mTransportTypes = 0;
+        mNetworkCapabilities = mTransportTypes = mUnwantedNetworkCapabilities = 0;
         mLinkUpBandwidthKbps = mLinkDownBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED;
         mNetworkSpecifier = null;
         mSignalStrength = SIGNAL_STRENGTH_UNSPECIFIED;
@@ -92,6 +94,11 @@
      */
     private long mNetworkCapabilities;
 
+    /**
+     * If any capabilities specified here they must not exist in the matching Network.
+     */
+    private long mUnwantedNetworkCapabilities;
+
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = { "NET_CAPABILITY_" }, value = {
@@ -339,31 +346,55 @@
      * Adds the given capability to this {@code NetworkCapability} instance.
      * Multiple capabilities may be applied sequentially.  Note that when searching
      * for a network to satisfy a request, all capabilities requested must be satisfied.
+     * <p>
+     * If the given capability was previously added to the list of unwanted capabilities
+     * then the capability will also be removed from the list of unwanted capabilities.
      *
      * @param capability the capability to be added.
      * @return This NetworkCapabilities instance, to facilitate chaining.
      * @hide
      */
     public NetworkCapabilities addCapability(@NetCapability int capability) {
-        if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) {
-            throw new IllegalArgumentException("NetworkCapability out of range");
-        }
+        checkValidCapability(capability);
         mNetworkCapabilities |= 1 << capability;
+        mUnwantedNetworkCapabilities &= ~(1 << capability);  // remove from unwanted capability list
         return this;
     }
 
     /**
+     * Adds the given capability to the list of unwanted capabilities of this
+     * {@code NetworkCapability} instance.  Multiple unwanted capabilities may be applied
+     * sequentially.  Note that when searching for a network to satisfy a request, the network
+     * must not contain any capability from unwanted capability list.
+     * <p>
+     * If the capability was previously added to the list of required capabilities (for
+     * example, it was there by default or added using {@link #addCapability(int)} method), then
+     * it will be removed from the list of required capabilities as well.
+     *
+     * @see #addCapability(int)
+     * @hide
+     */
+    public void addUnwantedCapability(@NetCapability int capability) {
+        checkValidCapability(capability);
+        mUnwantedNetworkCapabilities |= 1 << capability;
+        mNetworkCapabilities &= ~(1 << capability);  // remove from requested capabilities
+    }
+
+    /**
      * Removes (if found) the given capability from this {@code NetworkCapability} instance.
+     * <p>
+     * Note that this method removes capabilities that was added via {@link #addCapability(int)},
+     * {@link #addUnwantedCapability(int)} or {@link #setCapabilities(int[], int[])} .
      *
      * @param capability the capability to be removed.
      * @return This NetworkCapabilities instance, to facilitate chaining.
      * @hide
      */
     public NetworkCapabilities removeCapability(@NetCapability int capability) {
-        if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) {
-            throw new IllegalArgumentException("NetworkCapability out of range");
-        }
-        mNetworkCapabilities &= ~(1 << capability);
+        checkValidCapability(capability);
+        final long mask = ~(1 << capability);
+        mNetworkCapabilities &= mask;
+        mUnwantedNetworkCapabilities &= mask;
         return this;
     }
 
@@ -393,30 +424,57 @@
     }
 
     /**
+     * Gets all the unwanted capabilities set on this {@code NetworkCapability} instance.
+     *
+     * @return an array of unwanted capability values for this instance.
+     * @hide
+     */
+    public @NetCapability int[] getUnwantedCapabilities() {
+        return BitUtils.unpackBits(mUnwantedNetworkCapabilities);
+    }
+
+
+    /**
      * Sets all the capabilities set on this {@code NetworkCapability} instance.
      * This overwrites any existing capabilities.
      *
      * @hide
      */
-    public void setCapabilities(@NetCapability int[] capabilities) {
+    public void setCapabilities(@NetCapability int[] capabilities,
+            @NetCapability int[] unwantedCapabilities) {
         mNetworkCapabilities = BitUtils.packBits(capabilities);
+        mUnwantedNetworkCapabilities = BitUtils.packBits(unwantedCapabilities);
     }
 
     /**
-     * Tests for the presence of a capabilitity on this instance.
+     * @deprecated use {@link #setCapabilities(int[], int[])}
+     * @hide
+     */
+    @Deprecated
+    public void setCapabilities(@NetCapability int[] capabilities) {
+        setCapabilities(capabilities, new int[] {});
+    }
+
+    /**
+     * Tests for the presence of a capability on this instance.
      *
      * @param capability the capabilities to be tested for.
      * @return {@code true} if set on this instance.
      */
     public boolean hasCapability(@NetCapability int capability) {
-        if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) {
-            return false;
-        }
-        return ((mNetworkCapabilities & (1 << capability)) != 0);
+        return isValidCapability(capability)
+                && ((mNetworkCapabilities & (1 << capability)) != 0);
+    }
+
+    /** @hide */
+    public boolean hasUnwantedCapability(@NetCapability int capability) {
+        return isValidCapability(capability)
+                && ((mUnwantedNetworkCapabilities & (1 << capability)) != 0);
     }
 
     private void combineNetCapabilities(NetworkCapabilities nc) {
         this.mNetworkCapabilities |= nc.mNetworkCapabilities;
+        this.mUnwantedNetworkCapabilities |= nc.mUnwantedNetworkCapabilities;
     }
 
     /**
@@ -427,7 +485,9 @@
      * @hide
      */
     public String describeFirstNonRequestableCapability() {
-        final long nonRequestable = (mNetworkCapabilities & NON_REQUESTABLE_CAPABILITIES);
+        final long nonRequestable = (mNetworkCapabilities | mUnwantedNetworkCapabilities)
+                & NON_REQUESTABLE_CAPABILITIES;
+
         if (nonRequestable != 0) {
             return capabilityNameOf(BitUtils.unpackBits(nonRequestable)[0]);
         }
@@ -437,21 +497,29 @@
     }
 
     private boolean satisfiedByNetCapabilities(NetworkCapabilities nc, boolean onlyImmutable) {
-        long networkCapabilities = this.mNetworkCapabilities;
+        long requestedCapabilities = mNetworkCapabilities;
+        long requestedUnwantedCapabilities = mUnwantedNetworkCapabilities;
+        long providedCapabilities = nc.mNetworkCapabilities;
+
         if (onlyImmutable) {
-            networkCapabilities = networkCapabilities & ~MUTABLE_CAPABILITIES;
+            requestedCapabilities &= ~MUTABLE_CAPABILITIES;
+            requestedUnwantedCapabilities &= ~MUTABLE_CAPABILITIES;
         }
-        return ((nc.mNetworkCapabilities & networkCapabilities) == networkCapabilities);
+        return ((providedCapabilities & requestedCapabilities) == requestedCapabilities)
+                && ((requestedUnwantedCapabilities & providedCapabilities) == 0);
     }
 
     /** @hide */
     public boolean equalsNetCapabilities(NetworkCapabilities nc) {
-        return (nc.mNetworkCapabilities == this.mNetworkCapabilities);
+        return (nc.mNetworkCapabilities == this.mNetworkCapabilities)
+                && (nc.mUnwantedNetworkCapabilities == this.mUnwantedNetworkCapabilities);
     }
 
     private boolean equalsNetCapabilitiesRequestable(NetworkCapabilities that) {
         return ((this.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES) ==
-                (that.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES));
+                (that.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES))
+                && ((this.mUnwantedNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES) ==
+                (that.mUnwantedNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES));
     }
 
     /**
@@ -1185,15 +1253,17 @@
 
     @Override
     public int hashCode() {
-        return ((int) (mNetworkCapabilities & 0xFFFFFFFF)
+        return (int) (mNetworkCapabilities & 0xFFFFFFFF)
                 + ((int) (mNetworkCapabilities >> 32) * 3)
-                + ((int) (mTransportTypes & 0xFFFFFFFF) * 5)
-                + ((int) (mTransportTypes >> 32) * 7)
-                + (mLinkUpBandwidthKbps * 11)
-                + (mLinkDownBandwidthKbps * 13)
-                + Objects.hashCode(mNetworkSpecifier) * 17
-                + (mSignalStrength * 19)
-                + Objects.hashCode(mUids) * 23);
+                + ((int) (mUnwantedNetworkCapabilities & 0xFFFFFFFF) * 5)
+                + ((int) (mUnwantedNetworkCapabilities >> 32) * 7)
+                + ((int) (mTransportTypes & 0xFFFFFFFF) * 11)
+                + ((int) (mTransportTypes >> 32) * 13)
+                + (mLinkUpBandwidthKbps * 17)
+                + (mLinkDownBandwidthKbps * 19)
+                + Objects.hashCode(mNetworkSpecifier) * 23
+                + (mSignalStrength * 29)
+                + Objects.hashCode(mUids) * 31;
     }
 
     @Override
@@ -1203,6 +1273,7 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeLong(mNetworkCapabilities);
+        dest.writeLong(mUnwantedNetworkCapabilities);
         dest.writeLong(mTransportTypes);
         dest.writeInt(mLinkUpBandwidthKbps);
         dest.writeInt(mLinkDownBandwidthKbps);
@@ -1218,6 +1289,7 @@
                 NetworkCapabilities netCap = new NetworkCapabilities();
 
                 netCap.mNetworkCapabilities = in.readLong();
+                netCap.mUnwantedNetworkCapabilities = in.readLong();
                 netCap.mTransportTypes = in.readLong();
                 netCap.mLinkUpBandwidthKbps = in.readInt();
                 netCap.mLinkDownBandwidthKbps = in.readInt();
@@ -1246,6 +1318,11 @@
             appendStringRepresentationOfBitMaskToStringBuilder(sb, mNetworkCapabilities,
                     NetworkCapabilities::capabilityNameOf, "&");
         }
+        if (0 != mNetworkCapabilities) {
+            sb.append(" Unwanted: ");
+            appendStringRepresentationOfBitMaskToStringBuilder(sb, mUnwantedNetworkCapabilities,
+                    NetworkCapabilities::capabilityNameOf, "&");
+        }
         if (mLinkUpBandwidthKbps > 0) {
             sb.append(" LinkUpBandwidth>=").append(mLinkUpBandwidthKbps).append("Kbps");
         }
@@ -1396,4 +1473,13 @@
         Preconditions.checkArgument(
                 isValidTransport(transport), "Invalid TransportType " + transport);
     }
+
+    private static boolean isValidCapability(@NetworkCapabilities.NetCapability int capability) {
+        return capability >= MIN_NET_CAPABILITY && capability <= MAX_NET_CAPABILITY;
+    }
+
+    private static void checkValidCapability(@NetworkCapabilities.NetCapability int capability) {
+        Preconditions.checkArgument(isValidCapability(capability),
+                "NetworkCapability " + capability + "out of range");
+    }
 }
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 61199f9..fdcc304 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -165,6 +165,9 @@
          * the requested network's required capabilities.  Note that when searching
          * for a network to satisfy a request, all capabilities requested must be
          * satisfied.
+         * <p>
+         * If the given capability was previously added to the list of unwanted capabilities
+         * then the capability will also be removed from the list of unwanted capabilities.
          *
          * @param capability The capability to add.
          * @return The builder to facilitate chaining
@@ -176,7 +179,8 @@
         }
 
         /**
-         * Removes (if found) the given capability from this builder instance.
+         * Removes (if found) the given capability from this builder instance from both required
+         * and unwanted capabilities lists.
          *
          * @param capability The capability to remove.
          * @return The builder to facilitate chaining.
@@ -201,6 +205,24 @@
         }
 
         /**
+         * Add a capability that must not exist in the requested network.
+         * <p>
+         * If the capability was previously added to the list of required capabilities (for
+         * example, it was there by default or added using {@link #addCapability(int)} method), then
+         * it will be removed from the list of required capabilities as well.
+         *
+         * @see #addCapability(int)
+         *
+         * @param capability The capability to add to unwanted capability list.
+         * @return The builder to facilitate chaining.
+         * @hide
+         */
+        public Builder addUnwantedCapability(@NetworkCapabilities.NetCapability int capability) {
+            mNetworkCapabilities.addUnwantedCapability(capability);
+            return this;
+        }
+
+        /**
          * Completely clears all the {@code NetworkCapabilities} from this builder instance,
          * removing even the capabilities that are set by default when the object is constructed.
          *
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 9a30487..7bc5d5b 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -294,8 +294,8 @@
     /**
      * jbd line is:
      * BATTERY_STATS_CHECKIN_VERSION, uid, which, "jbd",
-     * jobsDeferredEventCount, jobsDeferredCount, averageLatencyMillis,
-     * count at latency < 1 hr, count at latency < 2 hrs, count at latency < 6 hrs, beyond 6 hrs
+     * jobsDeferredEventCount, jobsDeferredCount, totalLatencyMillis,
+     * count at latency < 1 hr, count at latency 1 to 2 hrs, 2 to 4 hrs, 4 to 8 hrs, and past 8 hrs
      * <p>
      * @see #JOB_FRESHNESS_BUCKETS
      */
@@ -364,13 +364,14 @@
     /**
      * These are the thresholds for bucketing last time since a job was run for an app
      * that just moved to ACTIVE due to a launch. So if the last time a job ran was less
-     * than 30 minutes ago, then it's reasonably fresh, 2 hours ago, not so fresh and so
+     * than 1 hour ago, then it's reasonably fresh, 2 hours ago, not so fresh and so
      * on.
      */
     public static final long[] JOB_FRESHNESS_BUCKETS = {
             1 * 60 * 60 * 1000L,
             2 * 60 * 60 * 1000L,
-            6 * 60 * 60 * 1000L,
+            4 * 60 * 60 * 1000L,
+            8 * 60 * 60 * 1000L,
             Long.MAX_VALUE
     };
 
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 8fc6901..3c3c762 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -84,6 +84,7 @@
 import android.util.Log;
 import android.util.MemoryIntArray;
 import android.util.StatsLog;
+import android.view.textservice.TextServicesManager;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.widget.ILockSettings;
@@ -7970,6 +7971,10 @@
             CLONE_TO_MANAGED_PROFILE.add(LOCATION_MODE);
             CLONE_TO_MANAGED_PROFILE.add(LOCATION_PROVIDERS_ALLOWED);
             CLONE_TO_MANAGED_PROFILE.add(SELECTED_INPUT_METHOD_SUBTYPE);
+            if (TextServicesManager.DISABLE_PER_PROFILE_SPELL_CHECKER) {
+                CLONE_TO_MANAGED_PROFILE.add(SELECTED_SPELL_CHECKER);
+                CLONE_TO_MANAGED_PROFILE.add(SELECTED_SPELL_CHECKER_SUBTYPE);
+            }
         }
 
         /** @hide */
@@ -10612,6 +10617,15 @@
         public static final String OFF_BODY_RADIOS_OFF_DELAY_MS = "off_body_radios_off_delay_ms";
 
         /**
+         * Whether or not to turn on Wifi when proxy is disconnected.
+         * Type: int (0 for false, 1 for true)
+         * Default: 1
+         * @hide
+         */
+        public static final String WIFI_ON_WHEN_PROXY_DISCONNECTED
+                = "wifi_on_when_proxy_disconnected";
+
+        /**
          * Whether or not to enable Time Only Mode for watch type devices.
          * Type: int (0 for false, 1 for true)
          * Default: 0
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 914ba0c..75940e8 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -283,6 +283,11 @@
      */
     oneway void setPipVisibility(boolean visible);
 
+   /**
+     * Called by System UI to enable or disable haptic feedback on the navigation bar buttons.
+     */
+    void setNavBarVirtualKeyHapticFeedbackEnabled(boolean enabled);
+
     /**
      * Device has a software navigation bar (separate from the status bar).
      */
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index e285222..03c3ded 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -14003,7 +14003,7 @@
                 // setFlags invocation.
                 shouldNotifyFocusableAvailable = true;
             } else {
-                if (hasFocus()) clearFocus();
+                if (isFocused()) clearFocus();
             }
         }
 
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index eba9176..e554540 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -21,7 +21,6 @@
 import android.inputmethodservice.InputMethodService;
 import android.os.Bundle;
 import android.os.Handler;
-import android.os.LocaleList;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 
@@ -899,37 +898,4 @@
      */
     boolean commitContent(@NonNull InputContentInfo inputContentInfo, int flags,
             @Nullable Bundle opts);
-
-    /**
-     * Called by the input method to tell a hint about the locales of text to be committed.
-     *
-     * <p>This is just a hint for editor authors (and the system) to choose better options when
-     * they have to disambiguate languages, like editor authors can do for input methods with
-     * {@link EditorInfo#hintLocales}.</p>
-     *
-     * <p>The language hint provided by this callback should have higher priority than
-     * {@link InputMethodSubtype#getLanguageTag()}, which cannot be updated dynamically.</p>
-     *
-     * <p>Note that in general it is discouraged for input method to specify
-     * {@link android.text.style.LocaleSpan} when inputting text, mainly because of application
-     * compatibility concerns.</p>
-     * <ul>
-     *     <li>When an existing text that already has {@link android.text.style.LocaleSpan} is being
-     *     modified by both the input method and application, there is no reliable and easy way to
-     *     keep track of who modified {@link android.text.style.LocaleSpan}. For instance, if the
-     *     text was updated by JavaScript, it it highly likely that span information is completely
-     *     removed, while some input method attempts to preserve spans if possible.</li>
-     *     <li>There is no clear semantics regarding whether {@link android.text.style.LocaleSpan}
-     *     means a weak (ignorable) hint or a strong hint. This becomes more problematic when
-     *     multiple {@link android.text.style.LocaleSpan} instances are specified to the same
-     *     text region, especially when those spans are conflicting.</li>
-     * </ul>
-     * @param languageHint list of languages sorted by the priority and/or probability
-     */
-    default void reportLanguageHint(@NonNull LocaleList languageHint) {
-        // Intentionally empty.
-        //
-        // We need to have *some* default implementation for the source compatibility.
-        // See Bug 72127682 for details.
-    }
 }
diff --git a/core/java/android/view/inputmethod/InputConnectionWrapper.java b/core/java/android/view/inputmethod/InputConnectionWrapper.java
index cbe6856..f671e22 100644
--- a/core/java/android/view/inputmethod/InputConnectionWrapper.java
+++ b/core/java/android/view/inputmethod/InputConnectionWrapper.java
@@ -16,10 +16,8 @@
 
 package android.view.inputmethod;
 
-import android.annotation.NonNull;
 import android.os.Bundle;
 import android.os.Handler;
-import android.os.LocaleList;
 import android.view.KeyEvent;
 
 /**
@@ -305,13 +303,4 @@
     public boolean commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) {
         return mTarget.commitContent(inputContentInfo, flags, opts);
     }
-
-    /**
-     * {@inheritDoc}
-     * @throws NullPointerException if the target is {@code null}.
-     */
-    @Override
-    public void reportLanguageHint(@NonNull LocaleList languageHint) {
-        mTarget.reportLanguageHint(languageHint);
-    }
 }
diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java
index f368c74..21ec42b 100644
--- a/core/java/android/view/textservice/TextServicesManager.java
+++ b/core/java/android/view/textservice/TextServicesManager.java
@@ -66,6 +66,12 @@
     private static final String TAG = TextServicesManager.class.getSimpleName();
     private static final boolean DBG = false;
 
+    /**
+     * A compile time switch to control per-profile spell checker, which is not yet ready.
+     * @hide
+     */
+    public static final boolean DISABLE_PER_PROFILE_SPELL_CHECKER = true;
+
     private static TextServicesManager sInstance;
 
     private final ITextServicesManager mService;
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index a13de75..9a99963 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -31,7 +31,6 @@
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.Handler;
-import android.os.LocaleList;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.StrictMode;
@@ -6036,11 +6035,6 @@
         public boolean commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) {
             return getTarget().commitContent(inputContentInfo, flags, opts);
         }
-
-        @Override
-        public void reportLanguageHint(@NonNull LocaleList languageHint) {
-            getTarget().reportLanguageHint(languageHint);
-        }
     }
 
     /**
diff --git a/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java b/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
index ffc21d5..90712fd 100644
--- a/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
+++ b/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
@@ -143,6 +143,9 @@
         mContext.getContentResolver().registerContentObserver(
                 Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN),
                 false, co, UserHandle.USER_ALL);
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN),
+                false, co, UserHandle.USER_ALL);
         setCurrentUser(mUserId);
     }
 
@@ -168,8 +171,12 @@
         final ContentResolver cr = mContext.getContentResolver();
         final boolean enabled = Settings.Secure.getIntForUser(
                 cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, 1, mUserId) == 1;
+        // Enable the shortcut from the lockscreen by default if the dialog has been shown
+        final int dialogAlreadyShown = Settings.Secure.getIntForUser(
+                cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 0, mUserId);
         mEnabledOnLockScreen = Settings.Secure.getIntForUser(
-                cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN, 0, mUserId) == 1;
+                cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN,
+                dialogAlreadyShown, mUserId) == 1;
         mIsShortcutEnabled = enabled && haveValidService;
     }
 
diff --git a/core/java/com/android/internal/globalactions/Action.java b/core/java/com/android/internal/globalactions/Action.java
new file mode 100644
index 0000000..ddb75c1c
--- /dev/null
+++ b/core/java/com/android/internal/globalactions/Action.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.globalactions;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+/** What each item in the global actions dialog must be able to support. */
+public interface Action {
+    /** @return Text that will be announced when dialog is created. {@code null} for none. */
+    CharSequence getLabelForAccessibility(Context context);
+
+    /** Create the view that represents this action. */
+    View create(Context context, View convertView, ViewGroup parent, LayoutInflater inflater);
+
+    /** Called when the action is selected by the user. */
+    void onPress();
+
+    /** @return whether this action should appear in the dialog when the keygaurd is showing. */
+    boolean showDuringKeyguard();
+
+    /** @return whether this action should appear in the dialog before the device is provisioned. */
+    boolean showBeforeProvisioning();
+
+    /** @return {@code true} if the action is enabled for user interaction. */
+    boolean isEnabled();
+}
diff --git a/core/java/com/android/internal/globalactions/ActionsAdapter.java b/core/java/com/android/internal/globalactions/ActionsAdapter.java
new file mode 100644
index 0000000..c9f01ce
--- /dev/null
+++ b/core/java/com/android/internal/globalactions/ActionsAdapter.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.globalactions;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import java.util.function.BooleanSupplier;
+import java.util.List;
+
+/**
+ * The adapter used for the list within the global actions dialog, taking into account whether the
+ * keyguard is showing via {@link LegacyGlobalActions#mKeyguardShowing} and whether the device is
+ * provisioned via {@link LegacyGlobalActions#mDeviceProvisioned}.
+ */
+public class ActionsAdapter extends BaseAdapter {
+    private final Context mContext;
+    private final List<Action> mItems;
+    private final BooleanSupplier mDeviceProvisioned;
+    private final BooleanSupplier mKeyguardShowing;
+
+    public ActionsAdapter(Context context, List<Action> items,
+            BooleanSupplier deviceProvisioned, BooleanSupplier keyguardShowing) {
+        mContext = context;
+        mItems = items;
+        mDeviceProvisioned = deviceProvisioned;
+        mKeyguardShowing = keyguardShowing;
+    }
+
+    @Override
+    public int getCount() {
+        final boolean keyguardShowing = mKeyguardShowing.getAsBoolean();
+        final boolean deviceProvisioned = mDeviceProvisioned.getAsBoolean();
+        int count = 0;
+
+        for (int i = 0; i < mItems.size(); i++) {
+            final Action action = mItems.get(i);
+
+            if (keyguardShowing && !action.showDuringKeyguard()) {
+                continue;
+            }
+            if (!deviceProvisioned && !action.showBeforeProvisioning()) {
+                continue;
+            }
+            count++;
+        }
+        return count;
+    }
+
+    @Override
+    public boolean isEnabled(int position) {
+        return getItem(position).isEnabled();
+    }
+
+    @Override
+    public boolean areAllItemsEnabled() {
+        return false;
+    }
+
+    @Override
+    public Action getItem(int position) {
+        final boolean keyguardShowing = mKeyguardShowing.getAsBoolean();
+        final boolean deviceProvisioned = mDeviceProvisioned.getAsBoolean();
+
+        int filteredPos = 0;
+        for (int i = 0; i < mItems.size(); i++) {
+            final Action action = mItems.get(i);
+            if (keyguardShowing && !action.showDuringKeyguard()) {
+                continue;
+            }
+            if (!deviceProvisioned && !action.showBeforeProvisioning()) {
+                continue;
+            }
+            if (filteredPos == position) {
+                return action;
+            }
+            filteredPos++;
+        }
+
+        throw new IllegalArgumentException("position " + position
+                + " out of range of showable actions"
+                + ", filtered count=" + getCount()
+                + ", keyguardshowing=" + keyguardShowing
+                + ", provisioned=" + deviceProvisioned);
+    }
+
+    @Override
+    public long getItemId(int position) {
+        return position;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        Action action = getItem(position);
+        return action.create(mContext, convertView, parent, LayoutInflater.from(mContext));
+    }
+}
diff --git a/core/java/com/android/internal/globalactions/ActionsDialog.java b/core/java/com/android/internal/globalactions/ActionsDialog.java
new file mode 100644
index 0000000..1cca1cc
--- /dev/null
+++ b/core/java/com/android/internal/globalactions/ActionsDialog.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.globalactions;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.util.TypedValue;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.KeyEvent;
+import android.widget.ListView;
+import com.android.internal.app.AlertController;
+
+/** A dialog that lists the given Action items to be user selectable. */
+public final class ActionsDialog extends Dialog implements DialogInterface {
+    private final Context mContext;
+    private final AlertController mAlert;
+    private final ActionsAdapter mAdapter;
+
+    public ActionsDialog(Context context, AlertController.AlertParams params) {
+        super(context, getDialogTheme(context));
+        mContext = getContext();
+        mAlert = AlertController.create(mContext, this, getWindow());
+        mAdapter = (ActionsAdapter) params.mAdapter;
+        params.apply(mAlert);
+    }
+
+    private static int getDialogTheme(Context context) {
+        TypedValue outValue = new TypedValue();
+        context.getTheme().resolveAttribute(com.android.internal.R.attr.alertDialogTheme,
+                outValue, true);
+        return outValue.resourceId;
+    }
+
+    @Override
+    protected void onStart() {
+        super.setCanceledOnTouchOutside(true);
+        super.onStart();
+    }
+
+    public ListView getListView() {
+        return mAlert.getListView();
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mAlert.installContent();
+    }
+
+    @Override
+    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+        if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
+            for (int i = 0; i < mAdapter.getCount(); ++i) {
+                CharSequence label =
+                        mAdapter.getItem(i).getLabelForAccessibility(getContext());
+                if (label != null) {
+                    event.getText().add(label);
+                }
+            }
+        }
+        return super.dispatchPopulateAccessibilityEvent(event);
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        if (mAlert.onKeyDown(keyCode, event)) {
+            return true;
+        }
+        return super.onKeyDown(keyCode, event);
+    }
+
+    @Override
+    public boolean onKeyUp(int keyCode, KeyEvent event) {
+        if (mAlert.onKeyUp(keyCode, event)) {
+            return true;
+        }
+        return super.onKeyUp(keyCode, event);
+    }
+}
diff --git a/core/java/com/android/internal/globalactions/LongPressAction.java b/core/java/com/android/internal/globalactions/LongPressAction.java
new file mode 100644
index 0000000..eed4cd9
--- /dev/null
+++ b/core/java/com/android/internal/globalactions/LongPressAction.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.globalactions;
+
+/** An action that also supports long press. */
+public interface LongPressAction extends Action {
+    boolean onLongPress();
+}
diff --git a/core/java/com/android/internal/globalactions/SinglePressAction.java b/core/java/com/android/internal/globalactions/SinglePressAction.java
new file mode 100644
index 0000000..0b8cd0b
--- /dev/null
+++ b/core/java/com/android/internal/globalactions/SinglePressAction.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.globalactions;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+import com.android.internal.R;
+
+/** A single press action maintains no state, just responds to a press and takes an action. */
+public abstract class SinglePressAction implements Action {
+    private final int mIconResId;
+    private final Drawable mIcon;
+    private final int mMessageResId;
+    private final CharSequence mMessage;
+
+    protected SinglePressAction(int iconResId, int messageResId) {
+        mIconResId = iconResId;
+        mMessageResId = messageResId;
+        mMessage = null;
+        mIcon = null;
+    }
+
+    protected SinglePressAction(int iconResId, Drawable icon, CharSequence message) {
+        mIconResId = iconResId;
+        mMessageResId = 0;
+        mMessage = message;
+        mIcon = icon;
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return true;
+    }
+
+    public String getStatus() {
+        return null;
+    }
+
+    @Override
+    abstract public void onPress();
+
+    @Override
+    public CharSequence getLabelForAccessibility(Context context) {
+        if (mMessage != null) {
+            return mMessage;
+        } else {
+            return context.getString(mMessageResId);
+        }
+    }
+
+    @Override
+    public View create(
+            Context context, View convertView, ViewGroup parent, LayoutInflater inflater) {
+        View v = inflater.inflate(R.layout.global_actions_item, parent, false);
+
+        ImageView icon = v.findViewById(R.id.icon);
+        TextView messageView = v.findViewById(R.id.message);
+
+        TextView statusView = v.findViewById(R.id.status);
+        final String status = getStatus();
+        if (!TextUtils.isEmpty(status)) {
+            statusView.setText(status);
+        } else {
+            statusView.setVisibility(View.GONE);
+        }
+        if (mIcon != null) {
+            icon.setImageDrawable(mIcon);
+            icon.setScaleType(ImageView.ScaleType.CENTER_CROP);
+        } else if (mIconResId != 0) {
+            icon.setImageDrawable(context.getDrawable(mIconResId));
+        }
+        if (mMessage != null) {
+            messageView.setText(mMessage);
+        } else {
+            messageView.setText(mMessageResId);
+        }
+
+        return v;
+    }
+}
diff --git a/core/java/com/android/internal/globalactions/ToggleAction.java b/core/java/com/android/internal/globalactions/ToggleAction.java
new file mode 100644
index 0000000..9167958
--- /dev/null
+++ b/core/java/com/android/internal/globalactions/ToggleAction.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.globalactions;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+import com.android.internal.R;
+
+/**
+ * A toggle action knows whether it is on or off, and displays an icon and status message
+ * accordingly.
+ */
+public abstract class ToggleAction implements Action {
+    private static final String TAG = "ToggleAction";
+
+    public enum State {
+        Off(false),
+        TurningOn(true),
+        TurningOff(true),
+        On(false);
+
+        private final boolean inTransition;
+
+        State(boolean intermediate) {
+            inTransition = intermediate;
+        }
+
+        public boolean inTransition() {
+            return inTransition;
+        }
+    }
+
+    protected State mState = State.Off;
+
+    // prefs
+    protected int mEnabledIconResId;
+    protected int mDisabledIconResid;
+    protected int mMessageResId;
+    protected int mEnabledStatusMessageResId;
+    protected int mDisabledStatusMessageResId;
+
+    /**
+     * @param enabledIconResId The icon for when this action is on.
+     * @param disabledIconResid The icon for when this action is off.
+     * @param message The general information message, e.g 'Silent Mode'
+     * @param enabledStatusMessageResId The on status message, e.g 'sound disabled'
+     * @param disabledStatusMessageResId The off status message, e.g. 'sound enabled'
+     */
+    public ToggleAction(int enabledIconResId,
+            int disabledIconResid,
+            int message,
+            int enabledStatusMessageResId,
+            int disabledStatusMessageResId) {
+        mEnabledIconResId = enabledIconResId;
+        mDisabledIconResid = disabledIconResid;
+        mMessageResId = message;
+        mEnabledStatusMessageResId = enabledStatusMessageResId;
+        mDisabledStatusMessageResId = disabledStatusMessageResId;
+    }
+
+    /** Override to make changes to resource IDs just before creating the View. */
+    void willCreate() {
+
+    }
+
+    @Override
+    public CharSequence getLabelForAccessibility(Context context) {
+        return context.getString(mMessageResId);
+    }
+
+    @Override
+    public View create(Context context, View convertView, ViewGroup parent,
+            LayoutInflater inflater) {
+        willCreate();
+
+        View v = inflater.inflate(R.layout.global_actions_item, parent, false);
+
+        ImageView icon = v.findViewById(R.id.icon);
+        TextView messageView = v.findViewById(R.id.message);
+        TextView statusView = v.findViewById(R.id.status);
+        final boolean enabled = isEnabled();
+
+        if (messageView != null) {
+            messageView.setText(mMessageResId);
+            messageView.setEnabled(enabled);
+        }
+
+        boolean on = ((mState == State.On) || (mState == State.TurningOn));
+        if (icon != null) {
+            icon.setImageDrawable(context.getDrawable(
+                    (on ? mEnabledIconResId : mDisabledIconResid)));
+            icon.setEnabled(enabled);
+        }
+
+        if (statusView != null) {
+            statusView.setText(on ? mEnabledStatusMessageResId : mDisabledStatusMessageResId);
+            statusView.setVisibility(View.VISIBLE);
+            statusView.setEnabled(enabled);
+        }
+        v.setEnabled(enabled);
+
+        return v;
+    }
+
+    @Override
+    public final void onPress() {
+        if (mState.inTransition()) {
+            Log.w(TAG, "shouldn't be able to toggle when in transition");
+            return;
+        }
+
+        final boolean nowOn = !(mState == State.On);
+        onToggle(nowOn);
+        changeStateFromPress(nowOn);
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return !mState.inTransition();
+    }
+
+    /**
+     * Implementations may override this if their state can be in on of the intermediate
+     * states until some notification is received (e.g airplane mode is 'turning off' until
+     * we know the wireless connections are back online
+     * @param buttonOn Whether the button was turned on or off
+     */
+    protected void changeStateFromPress(boolean buttonOn) {
+        mState = buttonOn ? State.On : State.Off;
+    }
+
+    public abstract void onToggle(boolean on);
+
+    public void updateState(State state) {
+        mState = state;
+    }
+}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 242f422..4ab2fec 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -7872,12 +7872,10 @@
                 return;
             }
             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
-            final long averageLatency = deferredEventCount != 0
-                    ? mJobsFreshnessTimeMs.getCountLocked(which) / deferredEventCount
-                    : 0L;
+            final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
             sb.append(deferredEventCount); sb.append(',');
             sb.append(deferredCount); sb.append(',');
-            sb.append(averageLatency);
+            sb.append(totalLatency);
             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
                 if (mJobsFreshnessBuckets[i] == null) {
                     sb.append(",0");
@@ -7896,12 +7894,10 @@
                 return;
             }
             final int deferredCount = mJobsDeferredCount.getCountLocked(which);
-            final long averageLatency = deferredEventCount != 0
-                    ? mJobsFreshnessTimeMs.getCountLocked(which) / deferredEventCount
-                    : 0L;
+            final long totalLatency = mJobsFreshnessTimeMs.getCountLocked(which);
             sb.append("times="); sb.append(deferredEventCount); sb.append(", ");
             sb.append("count="); sb.append(deferredCount); sb.append(", ");
-            sb.append("avgLatency="); sb.append(averageLatency); sb.append(", ");
+            sb.append("totalLatencyMs="); sb.append(totalLatency); sb.append(", ");
             for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
                 sb.append("<"); sb.append(JOB_FRESHNESS_BUCKETS[i]); sb.append("ms=");
                 if (mJobsFreshnessBuckets[i] == null) {
diff --git a/core/java/com/android/internal/os/logging/MetricsLoggerWrapper.java b/core/java/com/android/internal/os/logging/MetricsLoggerWrapper.java
index adad036..bfe3780 100644
--- a/core/java/com/android/internal/os/logging/MetricsLoggerWrapper.java
+++ b/core/java/com/android/internal/os/logging/MetricsLoggerWrapper.java
@@ -21,6 +21,7 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.util.Pair;
 import android.util.StatsLog;
+import android.view.WindowManager.LayoutParams;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -103,13 +104,27 @@
                 StatsLog.PICTURE_IN_PICTURE_STATE_CHANGED__STATE__EXPANDED_TO_FULL_SCREEN);
     }
 
-    public static void logAppOverlayEnter(int uid, String packageName, boolean usingAlertWindow) {
-        StatsLog.write(StatsLog.OVERLAY_STATE_CHANGED, uid, packageName, usingAlertWindow,
-                StatsLog.OVERLAY_STATE_CHANGED__STATE__ENTERED);
+    public static void logAppOverlayEnter(int uid, String packageName, boolean changed, int type, boolean usingAlertWindow) {
+        if (changed) {
+            if (type != LayoutParams.TYPE_APPLICATION_OVERLAY) {
+                StatsLog.write(StatsLog.OVERLAY_STATE_CHANGED, uid, packageName, true,
+                        StatsLog.OVERLAY_STATE_CHANGED__STATE__ENTERED);
+            } else if (!usingAlertWindow){
+                StatsLog.write(StatsLog.OVERLAY_STATE_CHANGED, uid, packageName, false,
+                        StatsLog.OVERLAY_STATE_CHANGED__STATE__ENTERED);
+            }
+        }
     }
 
-    public static void logAppOverlayExit(int uid, String packageName, boolean usingAlertWindow) {
-        StatsLog.write(StatsLog.OVERLAY_STATE_CHANGED, uid, packageName, usingAlertWindow,
-                StatsLog.OVERLAY_STATE_CHANGED__STATE__EXITED);
+    public static void logAppOverlayExit(int uid, String packageName, boolean changed, int type, boolean usingAlertWindow) {
+        if (changed) {
+            if (type != LayoutParams.TYPE_APPLICATION_OVERLAY) {
+                StatsLog.write(StatsLog.OVERLAY_STATE_CHANGED, uid, packageName, true,
+                        StatsLog.OVERLAY_STATE_CHANGED__STATE__EXITED);
+            } else if (!usingAlertWindow){
+                StatsLog.write(StatsLog.OVERLAY_STATE_CHANGED, uid, packageName, false,
+                        StatsLog.OVERLAY_STATE_CHANGED__STATE__EXITED);
+            }
+        }
     }
 }
diff --git a/core/java/com/android/internal/textservice/LazyIntToIntMap.java b/core/java/com/android/internal/textservice/LazyIntToIntMap.java
new file mode 100644
index 0000000..ca9936c
--- /dev/null
+++ b/core/java/com/android/internal/textservice/LazyIntToIntMap.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.textservice;
+
+import android.annotation.NonNull;
+import android.util.SparseIntArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.function.IntUnaryOperator;
+
+/**
+ * Simple int-to-int key-value-store that is to be lazily initialized with the given
+ * {@link IntUnaryOperator}.
+ */
+@VisibleForTesting
+public final class LazyIntToIntMap {
+
+    private final SparseIntArray mMap = new SparseIntArray();
+
+    @NonNull
+    private final IntUnaryOperator mMappingFunction;
+
+    /**
+     * @param mappingFunction int to int mapping rules to be (lazily) evaluated
+     */
+    public LazyIntToIntMap(@NonNull IntUnaryOperator mappingFunction) {
+        mMappingFunction = mappingFunction;
+    }
+
+    /**
+     * Deletes {@code key} and associated value.
+     * @param key key to be deleted
+     */
+    public void delete(int key) {
+        mMap.delete(key);
+    }
+
+    /**
+     * @param key key associated with the value
+     * @return value associated with the {@code key}. If this is the first time to access
+     * {@code key}, then {@code mappingFunction} passed to the constructor will be evaluated
+     */
+    public int get(int key) {
+        final int index = mMap.indexOfKey(key);
+        if (index >= 0) {
+            return mMap.valueAt(index);
+        }
+        final int value = mMappingFunction.applyAsInt(key);
+        mMap.append(key, value);
+        return value;
+    }
+}
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index e08caa8..28291ae 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -23,7 +23,6 @@
 import android.annotation.Nullable;
 import android.os.Bundle;
 import android.os.Handler;
-import android.os.LocaleList;
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
@@ -65,7 +64,6 @@
     private static final int DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO = 140;
     private static final int DO_CLOSE_CONNECTION = 150;
     private static final int DO_COMMIT_CONTENT = 160;
-    private static final int DO_REPORT_LANGUAGE_HINT = 170;
 
     @GuardedBy("mLock")
     @Nullable
@@ -219,10 +217,6 @@
                 callback));
     }
 
-    public void reportLanguageHint(@NonNull LocaleList languageHint) {
-        dispatchMessage(obtainMessageO(DO_REPORT_LANGUAGE_HINT, languageHint));
-    }
-
     void dispatchMessage(Message msg) {
         // If we are calling this from the main thread, then we can call
         // right through.  Otherwise, we need to send the message to the
@@ -583,16 +577,6 @@
                 }
                 return;
             }
-            case DO_REPORT_LANGUAGE_HINT: {
-                final LocaleList languageHint = (LocaleList) msg.obj;
-                final InputConnection ic = getInputConnection();
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "reportLanguageHint on inactive InputConnection");
-                    return;
-                }
-                ic.reportLanguageHint(languageHint);
-                return;
-            }
         }
         Log.w(TAG, "Unhandled message code: " + msg.what);
     }
diff --git a/core/java/com/android/internal/view/IInputContext.aidl b/core/java/com/android/internal/view/IInputContext.aidl
index e69a87ff..c227991 100644
--- a/core/java/com/android/internal/view/IInputContext.aidl
+++ b/core/java/com/android/internal/view/IInputContext.aidl
@@ -17,7 +17,6 @@
 package com.android.internal.view;
 
 import android.os.Bundle;
-import android.os.LocaleList;
 import android.view.KeyEvent;
 import android.view.inputmethod.CompletionInfo;
 import android.view.inputmethod.CorrectionInfo;
@@ -79,6 +78,4 @@
 
     void commitContent(in InputContentInfo inputContentInfo, int flags, in Bundle opts, int sec,
             IInputContextCallback callback);
-
-    void reportLanguageHint(in LocaleList languageHint);
 }
diff --git a/core/java/com/android/internal/view/InputConnectionWrapper.java b/core/java/com/android/internal/view/InputConnectionWrapper.java
index 34be598..5b65bbe 100644
--- a/core/java/com/android/internal/view/InputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/InputConnectionWrapper.java
@@ -22,7 +22,6 @@
 import android.inputmethodservice.AbstractInputMethodService;
 import android.os.Bundle;
 import android.os.Handler;
-import android.os.LocaleList;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.util.Log;
@@ -621,14 +620,6 @@
     }
 
     @AnyThread
-    public void reportLanguageHint(@NonNull LocaleList languageHint) {
-        try {
-            mIInputContext.reportLanguageHint(languageHint);
-        } catch (RemoteException e) {
-        }
-    }
-
-    @AnyThread
     private boolean isMethodMissing(@MissingMethodFlags final int methodFlag) {
         return (mMissingMethods & methodFlag) == methodFlag;
     }
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index b048977..1d22093 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -110,8 +110,8 @@
         "android_util_AssetManager.cpp",
         "android_util_Binder.cpp",
         "android_util_EventLog.cpp",
-        "android_util_MemoryIntArray.cpp",
         "android_util_Log.cpp",
+        "android_util_MemoryIntArray.cpp",
         "android_util_PathParser.cpp",
         "android_util_Process.cpp",
         "android_util_StringBlock.cpp",
@@ -191,6 +191,7 @@
         "android_backup_FileBackupHelperBase.cpp",
         "android_backup_BackupHelperDispatcher.cpp",
         "android_app_backup_FullBackup.cpp",
+        "android_content_res_ApkAssets.cpp",
         "android_content_res_ObbScanner.cpp",
         "android_content_res_Configuration.cpp",
         "android_animation_PropertyValuesHolder.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index f280c7a..5ae4a52 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -123,6 +123,7 @@
 extern int register_android_util_PathParser(JNIEnv* env);
 extern int register_android_content_StringBlock(JNIEnv* env);
 extern int register_android_content_XmlBlock(JNIEnv* env);
+extern int register_android_content_res_ApkAssets(JNIEnv* env);
 extern int register_android_graphics_Canvas(JNIEnv* env);
 extern int register_android_graphics_CanvasProperty(JNIEnv* env);
 extern int register_android_graphics_ColorFilter(JNIEnv* env);
@@ -1346,6 +1347,7 @@
     REG_JNI(register_android_content_AssetManager),
     REG_JNI(register_android_content_StringBlock),
     REG_JNI(register_android_content_XmlBlock),
+    REG_JNI(register_android_content_res_ApkAssets),
     REG_JNI(register_android_text_AndroidCharacter),
     REG_JNI(register_android_text_Hyphenator),
     REG_JNI(register_android_text_MeasuredParagraph),
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index 48aef4a..ed032c7 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -28,7 +28,7 @@
 #include <nativehelper/ScopedUtfChars.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/android_util_AssetManager.h>
-#include <androidfw/AssetManager.h>
+#include <androidfw/AssetManager2.h>
 #include "Utils.h"
 #include "FontUtils.h"
 
@@ -205,7 +205,8 @@
     NPE_CHECK_RETURN_ZERO(env, jpath);
 
     NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
-    AssetManager* mgr = assetManagerForJavaObject(env, jassetMgr);
+
+    Guarded<AssetManager2>* mgr = AssetManagerForJavaObject(env, jassetMgr);
     if (NULL == mgr) {
         builder->axes.clear();
         return false;
@@ -217,27 +218,33 @@
         return false;
     }
 
-    Asset* asset;
-    if (isAsset) {
-        asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
-    } else {
-        asset = cookie ? mgr->openNonAsset(static_cast<int32_t>(cookie), str.c_str(),
-                Asset::ACCESS_BUFFER) : mgr->openNonAsset(str.c_str(), Asset::ACCESS_BUFFER);
+    std::unique_ptr<Asset> asset;
+    {
+      ScopedLock<AssetManager2> locked_mgr(*mgr);
+      if (isAsset) {
+          asset = locked_mgr->Open(str.c_str(), Asset::ACCESS_BUFFER);
+      } else if (cookie > 0) {
+          // Valid java cookies are 1-based, but AssetManager cookies are 0-based.
+          asset = locked_mgr->OpenNonAsset(str.c_str(), static_cast<ApkAssetsCookie>(cookie - 1),
+                  Asset::ACCESS_BUFFER);
+      } else {
+          asset = locked_mgr->OpenNonAsset(str.c_str(), Asset::ACCESS_BUFFER);
+      }
     }
 
-    if (NULL == asset) {
+    if (nullptr == asset) {
         builder->axes.clear();
         return false;
     }
 
     const void* buf = asset->getBuffer(false);
     if (NULL == buf) {
-        delete asset;
         builder->axes.clear();
         return false;
     }
 
-    sk_sp<SkData> data(SkData::MakeWithProc(buf, asset->getLength(), releaseAsset, asset));
+    sk_sp<SkData> data(SkData::MakeWithProc(buf, asset->getLength(), releaseAsset,
+            asset.release()));
     return addSkTypeface(builder, std::move(data), ttcIndex, weight, isItalic);
 }
 
diff --git a/core/jni/android_app_NativeActivity.cpp b/core/jni/android_app_NativeActivity.cpp
index 09e37e1..49a24a3 100644
--- a/core/jni/android_app_NativeActivity.cpp
+++ b/core/jni/android_app_NativeActivity.cpp
@@ -361,7 +361,7 @@
     code->sdkVersion = sdkVersion;
 
     code->javaAssetManager = env->NewGlobalRef(jAssetMgr);
-    code->assetManager = assetManagerForJavaObject(env, jAssetMgr);
+    code->assetManager = NdkAssetManagerForJavaObject(env, jAssetMgr);
 
     if (obbDir != NULL) {
         dirStr = env->GetStringUTFChars(obbDir, NULL);
diff --git a/core/jni/android_content_res_ApkAssets.cpp b/core/jni/android_content_res_ApkAssets.cpp
new file mode 100644
index 0000000..7738d84
--- /dev/null
+++ b/core/jni/android_content_res_ApkAssets.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define ATRACE_TAG ATRACE_TAG_RESOURCES
+
+#include "android-base/macros.h"
+#include "android-base/stringprintf.h"
+#include "android-base/unique_fd.h"
+#include "androidfw/ApkAssets.h"
+#include "utils/misc.h"
+#include "utils/Trace.h"
+
+#include "core_jni_helpers.h"
+#include "jni.h"
+#include "nativehelper/ScopedUtfChars.h"
+
+using ::android::base::unique_fd;
+
+namespace android {
+
+static jlong NativeLoad(JNIEnv* env, jclass /*clazz*/, jstring java_path, jboolean system,
+                        jboolean force_shared_lib, jboolean overlay) {
+  ScopedUtfChars path(env, java_path);
+  if (path.c_str() == nullptr) {
+    return 0;
+  }
+
+  ATRACE_NAME(base::StringPrintf("LoadApkAssets(%s)", path.c_str()).c_str());
+
+  std::unique_ptr<const ApkAssets> apk_assets;
+  if (overlay) {
+    apk_assets = ApkAssets::LoadOverlay(path.c_str(), system);
+  } else if (force_shared_lib) {
+    apk_assets = ApkAssets::LoadAsSharedLibrary(path.c_str(), system);
+  } else {
+    apk_assets = ApkAssets::Load(path.c_str(), system);
+  }
+
+  if (apk_assets == nullptr) {
+    std::string error_msg = base::StringPrintf("Failed to load asset path %s", path.c_str());
+    jniThrowException(env, "java/io/IOException", error_msg.c_str());
+    return 0;
+  }
+  return reinterpret_cast<jlong>(apk_assets.release());
+}
+
+static jlong NativeLoadFromFd(JNIEnv* env, jclass /*clazz*/, jobject file_descriptor,
+                              jstring friendly_name, jboolean system, jboolean force_shared_lib) {
+  ScopedUtfChars friendly_name_utf8(env, friendly_name);
+  if (friendly_name_utf8.c_str() == nullptr) {
+    return 0;
+  }
+
+  ATRACE_NAME(base::StringPrintf("LoadApkAssetsFd(%s)", friendly_name_utf8.c_str()).c_str());
+
+  int fd = jniGetFDFromFileDescriptor(env, file_descriptor);
+  if (fd < 0) {
+    jniThrowException(env, "java/lang/IllegalArgumentException", "Bad FileDescriptor");
+    return 0;
+  }
+
+  unique_fd dup_fd(::dup(fd));
+  if (dup_fd < 0) {
+    jniThrowIOException(env, errno);
+    return 0;
+  }
+
+  std::unique_ptr<const ApkAssets> apk_assets = ApkAssets::LoadFromFd(std::move(dup_fd),
+                                                                      friendly_name_utf8.c_str(),
+                                                                      system, force_shared_lib);
+  if (apk_assets == nullptr) {
+    std::string error_msg = base::StringPrintf("Failed to load asset path %s from fd %d",
+                                               friendly_name_utf8.c_str(), dup_fd.get());
+    jniThrowException(env, "java/io/IOException", error_msg.c_str());
+    return 0;
+  }
+  return reinterpret_cast<jlong>(apk_assets.release());
+}
+
+static void NativeDestroy(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr) {
+  delete reinterpret_cast<ApkAssets*>(ptr);
+}
+
+static jstring NativeGetAssetPath(JNIEnv* env, jclass /*clazz*/, jlong ptr) {
+  const ApkAssets* apk_assets = reinterpret_cast<const ApkAssets*>(ptr);
+  return env->NewStringUTF(apk_assets->GetPath().c_str());
+}
+
+static jlong NativeGetStringBlock(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr) {
+  const ApkAssets* apk_assets = reinterpret_cast<const ApkAssets*>(ptr);
+  return reinterpret_cast<jlong>(apk_assets->GetLoadedArsc()->GetStringPool());
+}
+
+static jboolean NativeIsUpToDate(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr) {
+  const ApkAssets* apk_assets = reinterpret_cast<const ApkAssets*>(ptr);
+  (void)apk_assets;
+  return JNI_TRUE;
+}
+
+static jlong NativeOpenXml(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring file_name) {
+  ScopedUtfChars path_utf8(env, file_name);
+  if (path_utf8.c_str() == nullptr) {
+    return 0;
+  }
+
+  const ApkAssets* apk_assets = reinterpret_cast<const ApkAssets*>(ptr);
+  std::unique_ptr<Asset> asset = apk_assets->Open(path_utf8.c_str(),
+                                                  Asset::AccessMode::ACCESS_RANDOM);
+  if (asset == nullptr) {
+    jniThrowException(env, "java/io/FileNotFoundException", path_utf8.c_str());
+    return 0;
+  }
+
+  // DynamicRefTable is only needed when looking up resource references. Opening an XML file
+  // directly from an ApkAssets has no notion of proper resource references.
+  std::unique_ptr<ResXMLTree> xml_tree = util::make_unique<ResXMLTree>(nullptr /*dynamicRefTable*/);
+  status_t err = xml_tree->setTo(asset->getBuffer(true), asset->getLength(), true);
+  asset.reset();
+
+  if (err != NO_ERROR) {
+    jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
+    return 0;
+  }
+  return reinterpret_cast<jlong>(xml_tree.release());
+}
+
+// JNI registration.
+static const JNINativeMethod gApkAssetsMethods[] = {
+    {"nativeLoad", "(Ljava/lang/String;ZZZ)J", (void*)NativeLoad},
+    {"nativeLoadFromFd", "(Ljava/io/FileDescriptor;Ljava/lang/String;ZZ)J",
+        (void*)NativeLoadFromFd},
+    {"nativeDestroy", "(J)V", (void*)NativeDestroy},
+    {"nativeGetAssetPath", "(J)Ljava/lang/String;", (void*)NativeGetAssetPath},
+    {"nativeGetStringBlock", "(J)J", (void*)NativeGetStringBlock},
+    {"nativeIsUpToDate", "(J)Z", (void*)NativeIsUpToDate},
+    {"nativeOpenXml", "(JLjava/lang/String;)J", (void*)NativeOpenXml},
+};
+
+int register_android_content_res_ApkAssets(JNIEnv* env) {
+  return RegisterMethodsOrDie(env, "android/content/res/ApkAssets", gApkAssetsMethods,
+                              arraysize(gApkAssetsMethods));
+}
+
+}  // namespace android
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 683b4c4..8be6ed8 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -1,1851 +1,1449 @@
-/* //device/libs/android_runtime/android_util_AssetManager.cpp
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+/*
+ * Copyright 2006, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
+#define ATRACE_TAG ATRACE_TAG_RESOURCES
 #define LOG_TAG "asset"
 
-#include <android_runtime/android_util_AssetManager.h>
-
 #include <inttypes.h>
 #include <linux/capability.h>
 #include <stdio.h>
-#include <sys/types.h>
-#include <sys/wait.h>
 #include <sys/stat.h>
 #include <sys/system_properties.h>
+#include <sys/types.h>
+#include <sys/wait.h>
 
 #include <private/android_filesystem_config.h> // for AID_SYSTEM
 
-#include "androidfw/Asset.h"
-#include "androidfw/AssetManager.h"
-#include "androidfw/AttributeResolution.h"
-#include "androidfw/ResourceTypes.h"
+#include "android-base/logging.h"
+#include "android-base/properties.h"
+#include "android-base/stringprintf.h"
+#include "android_runtime/android_util_AssetManager.h"
 #include "android_runtime/AndroidRuntime.h"
 #include "android_util_Binder.h"
+#include "androidfw/Asset.h"
+#include "androidfw/AssetManager.h"
+#include "androidfw/AssetManager2.h"
+#include "androidfw/AttributeResolution.h"
+#include "androidfw/MutexGuard.h"
+#include "androidfw/ResourceTypes.h"
 #include "core_jni_helpers.h"
 #include "jni.h"
-#include <nativehelper/JNIHelp.h>
-#include <nativehelper/ScopedStringChars.h>
-#include <nativehelper/ScopedUtfChars.h>
+#include "nativehelper/JNIHelp.h"
+#include "nativehelper/ScopedPrimitiveArray.h"
+#include "nativehelper/ScopedStringChars.h"
+#include "nativehelper/ScopedUtfChars.h"
 #include "utils/Log.h"
 #include "utils/misc.h"
 #include "utils/String8.h"
+#include "utils/Trace.h"
 
 extern "C" int capget(cap_user_header_t hdrp, cap_user_data_t datap);
 extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
 
+using ::android::base::StringPrintf;
 
 namespace android {
 
-static const bool kThrowOnBadId = false;
-
 // ----------------------------------------------------------------------------
 
-static struct typedvalue_offsets_t
-{
-    jfieldID mType;
-    jfieldID mData;
-    jfieldID mString;
-    jfieldID mAssetCookie;
-    jfieldID mResourceId;
-    jfieldID mChangingConfigurations;
-    jfieldID mDensity;
+static struct typedvalue_offsets_t {
+  jfieldID mType;
+  jfieldID mData;
+  jfieldID mString;
+  jfieldID mAssetCookie;
+  jfieldID mResourceId;
+  jfieldID mChangingConfigurations;
+  jfieldID mDensity;
 } gTypedValueOffsets;
 
-static struct assetfiledescriptor_offsets_t
-{
-    jfieldID mFd;
-    jfieldID mStartOffset;
-    jfieldID mLength;
+static struct assetfiledescriptor_offsets_t {
+  jfieldID mFd;
+  jfieldID mStartOffset;
+  jfieldID mLength;
 } gAssetFileDescriptorOffsets;
 
-static struct assetmanager_offsets_t
-{
-    jfieldID mObject;
+static struct assetmanager_offsets_t {
+  jfieldID mObject;
 } gAssetManagerOffsets;
 
-static struct sparsearray_offsets_t
-{
-    jclass classObject;
-    jmethodID constructor;
-    jmethodID put;
+static struct {
+  jfieldID native_ptr;
+} gApkAssetsFields;
+
+static struct sparsearray_offsets_t {
+  jclass classObject;
+  jmethodID constructor;
+  jmethodID put;
 } gSparseArrayOffsets;
 
-static struct configuration_offsets_t
-{
-    jclass classObject;
-    jmethodID constructor;
-    jfieldID mSmallestScreenWidthDpOffset;
-    jfieldID mScreenWidthDpOffset;
-    jfieldID mScreenHeightDpOffset;
+static struct configuration_offsets_t {
+  jclass classObject;
+  jmethodID constructor;
+  jfieldID mSmallestScreenWidthDpOffset;
+  jfieldID mScreenWidthDpOffset;
+  jfieldID mScreenHeightDpOffset;
 } gConfigurationOffsets;
 
-jclass g_stringClass = NULL;
+jclass g_stringClass = nullptr;
 
 // ----------------------------------------------------------------------------
 
-static jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
-                      const Res_value& value, uint32_t ref, ssize_t block,
-                      uint32_t typeSpecFlags, ResTable_config* config = NULL);
+// Java asset cookies have 0 as an invalid cookie, but TypedArray expects < 0.
+constexpr inline static jint ApkAssetsCookieToJavaCookie(ApkAssetsCookie cookie) {
+  return cookie != kInvalidCookie ? static_cast<jint>(cookie + 1) : -1;
+}
 
-jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
-               const Res_value& value, uint32_t ref, ssize_t block,
-               uint32_t typeSpecFlags, ResTable_config* config)
-{
-    env->SetIntField(outValue, gTypedValueOffsets.mType, value.dataType);
-    env->SetIntField(outValue, gTypedValueOffsets.mAssetCookie,
-                     static_cast<jint>(table->getTableCookie(block)));
-    env->SetIntField(outValue, gTypedValueOffsets.mData, value.data);
-    env->SetObjectField(outValue, gTypedValueOffsets.mString, NULL);
-    env->SetIntField(outValue, gTypedValueOffsets.mResourceId, ref);
-    env->SetIntField(outValue, gTypedValueOffsets.mChangingConfigurations,
-            typeSpecFlags);
-    if (config != NULL) {
-        env->SetIntField(outValue, gTypedValueOffsets.mDensity, config->density);
-    }
-    return block;
+constexpr inline static ApkAssetsCookie JavaCookieToApkAssetsCookie(jint cookie) {
+  return cookie > 0 ? static_cast<ApkAssetsCookie>(cookie - 1) : kInvalidCookie;
 }
 
 // This is called by zygote (running as user root) as part of preloadResources.
-static void verifySystemIdmaps()
-{
-    pid_t pid;
-    char system_id[10];
+static void NativeVerifySystemIdmaps(JNIEnv* /*env*/, jclass /*clazz*/) {
+  switch (pid_t pid = fork()) {
+    case -1:
+      PLOG(ERROR) << "failed to fork for idmap";
+      break;
 
-    snprintf(system_id, sizeof(system_id), "%d", AID_SYSTEM);
+    // child
+    case 0: {
+      struct __user_cap_header_struct capheader;
+      struct __user_cap_data_struct capdata;
 
-    switch (pid = fork()) {
-        case -1:
-            ALOGE("failed to fork for idmap: %s", strerror(errno));
-            break;
-        case 0: // child
-            {
-                struct __user_cap_header_struct capheader;
-                struct __user_cap_data_struct capdata;
+      memset(&capheader, 0, sizeof(capheader));
+      memset(&capdata, 0, sizeof(capdata));
 
-                memset(&capheader, 0, sizeof(capheader));
-                memset(&capdata, 0, sizeof(capdata));
+      capheader.version = _LINUX_CAPABILITY_VERSION;
+      capheader.pid = 0;
 
-                capheader.version = _LINUX_CAPABILITY_VERSION;
-                capheader.pid = 0;
+      if (capget(&capheader, &capdata) != 0) {
+        PLOG(ERROR) << "capget";
+        exit(1);
+      }
 
-                if (capget(&capheader, &capdata) != 0) {
-                    ALOGE("capget: %s\n", strerror(errno));
-                    exit(1);
-                }
+      capdata.effective = capdata.permitted;
+      if (capset(&capheader, &capdata) != 0) {
+        PLOG(ERROR) << "capset";
+        exit(1);
+      }
 
-                capdata.effective = capdata.permitted;
-                if (capset(&capheader, &capdata) != 0) {
-                    ALOGE("capset: %s\n", strerror(errno));
-                    exit(1);
-                }
+      if (setgid(AID_SYSTEM) != 0) {
+        PLOG(ERROR) << "setgid";
+        exit(1);
+      }
 
-                if (setgid(AID_SYSTEM) != 0) {
-                    ALOGE("setgid: %s\n", strerror(errno));
-                    exit(1);
-                }
+      if (setuid(AID_SYSTEM) != 0) {
+        PLOG(ERROR) << "setuid";
+        exit(1);
+      }
 
-                if (setuid(AID_SYSTEM) != 0) {
-                    ALOGE("setuid: %s\n", strerror(errno));
-                    exit(1);
-                }
+      // Generic idmap parameters
+      const char* argv[8];
+      int argc = 0;
+      struct stat st;
 
-                // Generic idmap parameters
-                const char* argv[8];
-                int argc = 0;
-                struct stat st;
+      memset(argv, 0, sizeof(argv));
+      argv[argc++] = AssetManager::IDMAP_BIN;
+      argv[argc++] = "--scan";
+      argv[argc++] = AssetManager::TARGET_PACKAGE_NAME;
+      argv[argc++] = AssetManager::TARGET_APK_PATH;
+      argv[argc++] = AssetManager::IDMAP_DIR;
 
-                memset(argv, NULL, sizeof(argv));
-                argv[argc++] = AssetManager::IDMAP_BIN;
-                argv[argc++] = "--scan";
-                argv[argc++] = AssetManager::TARGET_PACKAGE_NAME;
-                argv[argc++] = AssetManager::TARGET_APK_PATH;
-                argv[argc++] = AssetManager::IDMAP_DIR;
-
-                // Directories to scan for overlays: if OVERLAY_THEME_DIR_PROPERTY is defined,
-                // use OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in addition to OVERLAY_DIR.
-                char subdir[PROP_VALUE_MAX];
-                int len = __system_property_get(AssetManager::OVERLAY_THEME_DIR_PROPERTY, subdir);
-                if (len > 0) {
-                    String8 overlayPath = String8(AssetManager::OVERLAY_DIR) + "/" + subdir;
-                    if (stat(overlayPath.string(), &st) == 0) {
-                        argv[argc++] = overlayPath.string();
-                    }
-                }
-                if (stat(AssetManager::OVERLAY_DIR, &st) == 0) {
-                    argv[argc++] = AssetManager::OVERLAY_DIR;
-                }
-
-                if (stat(AssetManager::PRODUCT_OVERLAY_DIR, &st) == 0) {
-                    argv[argc++] = AssetManager::PRODUCT_OVERLAY_DIR;
-                }
-
-                // Finally, invoke idmap (if any overlay directory exists)
-                if (argc > 5) {
-                    execv(AssetManager::IDMAP_BIN, (char* const*)argv);
-                    ALOGE("failed to execv for idmap: %s", strerror(errno));
-                    exit(1); // should never get here
-                } else {
-                    exit(0);
-                }
-            }
-            break;
-        default: // parent
-            waitpid(pid, NULL, 0);
-            break;
-    }
-}
-
-
-// ----------------------------------------------------------------------------
-
-// this guy is exported to other jni routines
-AssetManager* assetManagerForJavaObject(JNIEnv* env, jobject obj)
-{
-    jlong amHandle = env->GetLongField(obj, gAssetManagerOffsets.mObject);
-    AssetManager* am = reinterpret_cast<AssetManager*>(amHandle);
-    if (am != NULL) {
-        return am;
-    }
-    jniThrowException(env, "java/lang/IllegalStateException", "AssetManager has been finalized!");
-    return NULL;
-}
-
-static jlong android_content_AssetManager_openAsset(JNIEnv* env, jobject clazz,
-                                                jstring fileName, jint mode)
-{
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return 0;
-    }
-
-    ALOGV("openAsset in %p (Java object %p)\n", am, clazz);
-
-    ScopedUtfChars fileName8(env, fileName);
-    if (fileName8.c_str() == NULL) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", "Empty file name");
-        return -1;
-    }
-
-    if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
-        && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
-        return -1;
-    }
-
-    Asset* a = am->open(fileName8.c_str(), (Asset::AccessMode)mode);
-
-    if (a == NULL) {
-        jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
-        return -1;
-    }
-
-    //printf("Created Asset Stream: %p\n", a);
-
-    return reinterpret_cast<jlong>(a);
-}
-
-static jobject returnParcelFileDescriptor(JNIEnv* env, Asset* a, jlongArray outOffsets)
-{
-    off64_t startOffset, length;
-    int fd = a->openFileDescriptor(&startOffset, &length);
-    delete a;
-
-    if (fd < 0) {
-        jniThrowException(env, "java/io/FileNotFoundException",
-                "This file can not be opened as a file descriptor; it is probably compressed");
-        return NULL;
-    }
-
-    jlong* offsets = (jlong*)env->GetPrimitiveArrayCritical(outOffsets, 0);
-    if (offsets == NULL) {
-        close(fd);
-        return NULL;
-    }
-
-    offsets[0] = startOffset;
-    offsets[1] = length;
-
-    env->ReleasePrimitiveArrayCritical(outOffsets, offsets, 0);
-
-    jobject fileDesc = jniCreateFileDescriptor(env, fd);
-    if (fileDesc == NULL) {
-        close(fd);
-        return NULL;
-    }
-
-    return newParcelFileDescriptor(env, fileDesc);
-}
-
-static jobject android_content_AssetManager_openAssetFd(JNIEnv* env, jobject clazz,
-                                                jstring fileName, jlongArray outOffsets)
-{
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return NULL;
-    }
-
-    ALOGV("openAssetFd in %p (Java object %p)\n", am, clazz);
-
-    ScopedUtfChars fileName8(env, fileName);
-    if (fileName8.c_str() == NULL) {
-        return NULL;
-    }
-
-    Asset* a = am->open(fileName8.c_str(), Asset::ACCESS_RANDOM);
-
-    if (a == NULL) {
-        jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
-        return NULL;
-    }
-
-    //printf("Created Asset Stream: %p\n", a);
-
-    return returnParcelFileDescriptor(env, a, outOffsets);
-}
-
-static jlong android_content_AssetManager_openNonAssetNative(JNIEnv* env, jobject clazz,
-                                                         jint cookie,
-                                                         jstring fileName,
-                                                         jint mode)
-{
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return 0;
-    }
-
-    ALOGV("openNonAssetNative in %p (Java object %p)\n", am, clazz);
-
-    ScopedUtfChars fileName8(env, fileName);
-    if (fileName8.c_str() == NULL) {
-        return -1;
-    }
-
-    if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
-        && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
-        return -1;
-    }
-
-    Asset* a = cookie
-        ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(),
-                (Asset::AccessMode)mode)
-        : am->openNonAsset(fileName8.c_str(), (Asset::AccessMode)mode);
-
-    if (a == NULL) {
-        jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
-        return -1;
-    }
-
-    //printf("Created Asset Stream: %p\n", a);
-
-    return reinterpret_cast<jlong>(a);
-}
-
-static jobject android_content_AssetManager_openNonAssetFdNative(JNIEnv* env, jobject clazz,
-                                                         jint cookie,
-                                                         jstring fileName,
-                                                         jlongArray outOffsets)
-{
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return NULL;
-    }
-
-    ALOGV("openNonAssetFd in %p (Java object %p)\n", am, clazz);
-
-    ScopedUtfChars fileName8(env, fileName);
-    if (fileName8.c_str() == NULL) {
-        return NULL;
-    }
-
-    Asset* a = cookie
-        ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(), Asset::ACCESS_RANDOM)
-        : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_RANDOM);
-
-    if (a == NULL) {
-        jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
-        return NULL;
-    }
-
-    //printf("Created Asset Stream: %p\n", a);
-
-    return returnParcelFileDescriptor(env, a, outOffsets);
-}
-
-static jobjectArray android_content_AssetManager_list(JNIEnv* env, jobject clazz,
-                                                   jstring fileName)
-{
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return NULL;
-    }
-
-    ScopedUtfChars fileName8(env, fileName);
-    if (fileName8.c_str() == NULL) {
-        return NULL;
-    }
-
-    AssetDir* dir = am->openDir(fileName8.c_str());
-
-    if (dir == NULL) {
-        jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
-        return NULL;
-    }
-
-    size_t N = dir->getFileCount();
-
-    jobjectArray array = env->NewObjectArray(dir->getFileCount(),
-                                                g_stringClass, NULL);
-    if (array == NULL) {
-        delete dir;
-        return NULL;
-    }
-
-    for (size_t i=0; i<N; i++) {
-        const String8& name = dir->getFileName(i);
-        jstring str = env->NewStringUTF(name.string());
-        if (str == NULL) {
-            delete dir;
-            return NULL;
+      // Directories to scan for overlays: if OVERLAY_THEME_DIR_PROPERTY is defined,
+      // use OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in addition to OVERLAY_DIR.
+      std::string overlay_theme_path = base::GetProperty(AssetManager::OVERLAY_THEME_DIR_PROPERTY,
+                                                         "");
+      if (!overlay_theme_path.empty()) {
+        overlay_theme_path = std::string(AssetManager::OVERLAY_DIR) + "/" + overlay_theme_path;
+        if (stat(overlay_theme_path.c_str(), &st) == 0) {
+          argv[argc++] = overlay_theme_path.c_str();
         }
-        env->SetObjectArrayElement(array, i, str);
-        env->DeleteLocalRef(str);
-    }
+      }
 
-    delete dir;
+      if (stat(AssetManager::OVERLAY_DIR, &st) == 0) {
+        argv[argc++] = AssetManager::OVERLAY_DIR;
+      }
 
-    return array;
+      if (stat(AssetManager::PRODUCT_OVERLAY_DIR, &st) == 0) {
+        argv[argc++] = AssetManager::PRODUCT_OVERLAY_DIR;
+      }
+
+      // Finally, invoke idmap (if any overlay directory exists)
+      if (argc > 5) {
+        execv(AssetManager::IDMAP_BIN, (char* const*)argv);
+        PLOG(ERROR) << "failed to execv for idmap";
+        exit(1); // should never get here
+      } else {
+        exit(0);
+      }
+  } break;
+
+  // parent
+  default:
+    waitpid(pid, nullptr, 0);
+    break;
+  }
 }
 
-static void android_content_AssetManager_destroyAsset(JNIEnv* env, jobject clazz,
-                                                      jlong assetHandle)
-{
-    Asset* a = reinterpret_cast<Asset*>(assetHandle);
-
-    //printf("Destroying Asset Stream: %p\n", a);
-
-    if (a == NULL) {
-        jniThrowNullPointerException(env, "asset");
-        return;
-    }
-
-    delete a;
-}
-
-static jint android_content_AssetManager_readAssetChar(JNIEnv* env, jobject clazz,
-                                                       jlong assetHandle)
-{
-    Asset* a = reinterpret_cast<Asset*>(assetHandle);
-
-    if (a == NULL) {
-        jniThrowNullPointerException(env, "asset");
-        return -1;
-    }
-
-    uint8_t b;
-    ssize_t res = a->read(&b, 1);
-    return res == 1 ? b : -1;
-}
-
-static jint android_content_AssetManager_readAsset(JNIEnv* env, jobject clazz,
-                                                jlong assetHandle, jbyteArray bArray,
-                                                jint off, jint len)
-{
-    Asset* a = reinterpret_cast<Asset*>(assetHandle);
-
-    if (a == NULL || bArray == NULL) {
-        jniThrowNullPointerException(env, "asset");
-        return -1;
-    }
-
-    if (len == 0) {
-        return 0;
-    }
-
-    jsize bLen = env->GetArrayLength(bArray);
-    if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) {
-        jniThrowException(env, "java/lang/IndexOutOfBoundsException", "");
-        return -1;
-    }
-
-    jbyte* b = env->GetByteArrayElements(bArray, NULL);
-    ssize_t res = a->read(b+off, len);
-    env->ReleaseByteArrayElements(bArray, b, 0);
-
-    if (res > 0) return static_cast<jint>(res);
-
-    if (res < 0) {
-        jniThrowException(env, "java/io/IOException", "");
-    }
-    return -1;
-}
-
-static jlong android_content_AssetManager_seekAsset(JNIEnv* env, jobject clazz,
-                                                 jlong assetHandle,
-                                                 jlong offset, jint whence)
-{
-    Asset* a = reinterpret_cast<Asset*>(assetHandle);
-
-    if (a == NULL) {
-        jniThrowNullPointerException(env, "asset");
-        return -1;
-    }
-
-    return a->seek(
-        offset, (whence > 0) ? SEEK_END : (whence < 0 ? SEEK_SET : SEEK_CUR));
-}
-
-static jlong android_content_AssetManager_getAssetLength(JNIEnv* env, jobject clazz,
-                                                      jlong assetHandle)
-{
-    Asset* a = reinterpret_cast<Asset*>(assetHandle);
-
-    if (a == NULL) {
-        jniThrowNullPointerException(env, "asset");
-        return -1;
-    }
-
-    return a->getLength();
-}
-
-static jlong android_content_AssetManager_getAssetRemainingLength(JNIEnv* env, jobject clazz,
-                                                               jlong assetHandle)
-{
-    Asset* a = reinterpret_cast<Asset*>(assetHandle);
-
-    if (a == NULL) {
-        jniThrowNullPointerException(env, "asset");
-        return -1;
-    }
-
-    return a->getRemainingLength();
-}
-
-static jint android_content_AssetManager_addAssetPath(JNIEnv* env, jobject clazz,
-                                                       jstring path, jboolean appAsLib)
-{
-    ScopedUtfChars path8(env, path);
-    if (path8.c_str() == NULL) {
-        return 0;
-    }
-
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return 0;
-    }
-
-    int32_t cookie;
-    bool res = am->addAssetPath(String8(path8.c_str()), &cookie, appAsLib);
-
-    return (res) ? static_cast<jint>(cookie) : 0;
-}
-
-static jint android_content_AssetManager_addOverlayPath(JNIEnv* env, jobject clazz,
-                                                     jstring idmapPath)
-{
-    ScopedUtfChars idmapPath8(env, idmapPath);
-    if (idmapPath8.c_str() == NULL) {
-        return 0;
-    }
-
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return 0;
-    }
-
-    int32_t cookie;
-    bool res = am->addOverlayPath(String8(idmapPath8.c_str()), &cookie);
-
-    return (res) ? (jint)cookie : 0;
-}
-
-static jint android_content_AssetManager_addAssetFd(JNIEnv* env, jobject clazz,
-                                                    jobject fileDescriptor, jstring debugPathName,
-                                                    jboolean appAsLib)
-{
-    ScopedUtfChars debugPathName8(env, debugPathName);
-
-    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
-    if (fd < 0) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", "Bad FileDescriptor");
-        return 0;
-    }
-
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return 0;
-    }
-
-    int dupfd = ::dup(fd);
-    if (dupfd < 0) {
-        jniThrowIOException(env, errno);
-        return 0;
-    }
-
-    int32_t cookie;
-    bool res = am->addAssetFd(dupfd, String8(debugPathName8.c_str()), &cookie, appAsLib);
-
-    return (res) ? static_cast<jint>(cookie) : 0;
-}
-
-static jboolean android_content_AssetManager_isUpToDate(JNIEnv* env, jobject clazz)
-{
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return JNI_TRUE;
-    }
-    return am->isUpToDate() ? JNI_TRUE : JNI_FALSE;
-}
-
-static jobjectArray getLocales(JNIEnv* env, jobject clazz, bool includeSystemLocales)
-{
-    Vector<String8> locales;
-
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return NULL;
-    }
-
-    am->getLocales(&locales, includeSystemLocales);
-
-    const int N = locales.size();
-
-    jobjectArray result = env->NewObjectArray(N, g_stringClass, NULL);
-    if (result == NULL) {
-        return NULL;
-    }
-
-    for (int i=0; i<N; i++) {
-        jstring str = env->NewStringUTF(locales[i].string());
-        if (str == NULL) {
-            return NULL;
-        }
-        env->SetObjectArrayElement(result, i, str);
-        env->DeleteLocalRef(str);
-    }
-
-    return result;
-}
-
-static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz)
-{
-    return getLocales(env, clazz, true /* include system locales */);
-}
-
-static jobjectArray android_content_AssetManager_getNonSystemLocales(JNIEnv* env, jobject clazz)
-{
-    return getLocales(env, clazz, false /* don't include system locales */);
-}
-
-static jobject constructConfigurationObject(JNIEnv* env, const ResTable_config& config) {
-    jobject result = env->NewObject(gConfigurationOffsets.classObject,
-            gConfigurationOffsets.constructor);
-    if (result == NULL) {
-        return NULL;
-    }
-
-    env->SetIntField(result, gConfigurationOffsets.mSmallestScreenWidthDpOffset,
-            config.smallestScreenWidthDp);
-    env->SetIntField(result, gConfigurationOffsets.mScreenWidthDpOffset, config.screenWidthDp);
-    env->SetIntField(result, gConfigurationOffsets.mScreenHeightDpOffset, config.screenHeightDp);
-
-    return result;
-}
-
-static jobjectArray getSizeConfigurationsInternal(JNIEnv* env,
-        const Vector<ResTable_config>& configs) {
-    const int N = configs.size();
-    jobjectArray result = env->NewObjectArray(N, gConfigurationOffsets.classObject, NULL);
-    if (result == NULL) {
-        return NULL;
-    }
-
-    for (int i=0; i<N; i++) {
-        jobject config = constructConfigurationObject(env, configs[i]);
-        if (config == NULL) {
-            env->DeleteLocalRef(result);
-            return NULL;
-        }
-
-        env->SetObjectArrayElement(result, i, config);
-        env->DeleteLocalRef(config);
-    }
-
-    return result;
-}
-
-static jobjectArray android_content_AssetManager_getSizeConfigurations(JNIEnv* env, jobject clazz) {
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return NULL;
-    }
-
-    const ResTable& res(am->getResources());
-    Vector<ResTable_config> configs;
-    res.getConfigurations(&configs, false /* ignoreMipmap */, true /* ignoreAndroidPackage */);
-
-    return getSizeConfigurationsInternal(env, configs);
-}
-
-static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject clazz,
-                                                          jint mcc, jint mnc,
-                                                          jstring locale, jint orientation,
-                                                          jint touchscreen, jint density,
-                                                          jint keyboard, jint keyboardHidden,
-                                                          jint navigation,
-                                                          jint screenWidth, jint screenHeight,
-                                                          jint smallestScreenWidthDp,
-                                                          jint screenWidthDp, jint screenHeightDp,
-                                                          jint screenLayout, jint uiMode,
-                                                          jint colorMode, jint sdkVersion)
-{
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return;
-    }
-
-    ResTable_config config;
-    memset(&config, 0, sizeof(config));
-
-    const char* locale8 = locale != NULL ? env->GetStringUTFChars(locale, NULL) : NULL;
-
-    // Constants duplicated from Java class android.content.res.Configuration.
-    static const jint kScreenLayoutRoundMask = 0x300;
-    static const jint kScreenLayoutRoundShift = 8;
-
-    config.mcc = (uint16_t)mcc;
-    config.mnc = (uint16_t)mnc;
-    config.orientation = (uint8_t)orientation;
-    config.touchscreen = (uint8_t)touchscreen;
-    config.density = (uint16_t)density;
-    config.keyboard = (uint8_t)keyboard;
-    config.inputFlags = (uint8_t)keyboardHidden;
-    config.navigation = (uint8_t)navigation;
-    config.screenWidth = (uint16_t)screenWidth;
-    config.screenHeight = (uint16_t)screenHeight;
-    config.smallestScreenWidthDp = (uint16_t)smallestScreenWidthDp;
-    config.screenWidthDp = (uint16_t)screenWidthDp;
-    config.screenHeightDp = (uint16_t)screenHeightDp;
-    config.screenLayout = (uint8_t)screenLayout;
-    config.uiMode = (uint8_t)uiMode;
-    config.colorMode = (uint8_t)colorMode;
-    config.sdkVersion = (uint16_t)sdkVersion;
-    config.minorVersion = 0;
-
-    // In Java, we use a 32bit integer for screenLayout, while we only use an 8bit integer
-    // in C++. We must extract the round qualifier out of the Java screenLayout and put it
-    // into screenLayout2.
-    config.screenLayout2 =
-            (uint8_t)((screenLayout & kScreenLayoutRoundMask) >> kScreenLayoutRoundShift);
-
-    am->setConfiguration(config, locale8);
-
-    if (locale != NULL) env->ReleaseStringUTFChars(locale, locale8);
-}
-
-static jint android_content_AssetManager_getResourceIdentifier(JNIEnv* env, jobject clazz,
-                                                            jstring name,
-                                                            jstring defType,
-                                                            jstring defPackage)
-{
-    ScopedStringChars name16(env, name);
-    if (name16.get() == NULL) {
-        return 0;
-    }
-
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return 0;
-    }
-
-    const char16_t* defType16 = reinterpret_cast<const char16_t*>(defType)
-        ? reinterpret_cast<const char16_t*>(env->GetStringChars(defType, NULL))
-        : NULL;
-    jsize defTypeLen = defType
-        ? env->GetStringLength(defType) : 0;
-    const char16_t* defPackage16 = reinterpret_cast<const char16_t*>(defPackage)
-        ? reinterpret_cast<const char16_t*>(env->GetStringChars(defPackage,
-                                                                NULL))
-        : NULL;
-    jsize defPackageLen = defPackage
-        ? env->GetStringLength(defPackage) : 0;
-
-    jint ident = am->getResources().identifierForName(
-        reinterpret_cast<const char16_t*>(name16.get()), name16.size(),
-        defType16, defTypeLen, defPackage16, defPackageLen);
-
-    if (defPackage16) {
-        env->ReleaseStringChars(defPackage,
-                                reinterpret_cast<const jchar*>(defPackage16));
-    }
-    if (defType16) {
-        env->ReleaseStringChars(defType,
-                                reinterpret_cast<const jchar*>(defType16));
-    }
-
-    return ident;
-}
-
-static jstring android_content_AssetManager_getResourceName(JNIEnv* env, jobject clazz,
-                                                            jint resid)
-{
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return NULL;
-    }
-
-    ResTable::resource_name name;
-    if (!am->getResources().getResourceName(resid, true, &name)) {
-        return NULL;
-    }
-
-    String16 str;
-    if (name.package != NULL) {
-        str.setTo(name.package, name.packageLen);
-    }
-    if (name.type8 != NULL || name.type != NULL) {
-        if (str.size() > 0) {
-            char16_t div = ':';
-            str.append(&div, 1);
-        }
-        if (name.type8 != NULL) {
-            str.append(String16(name.type8, name.typeLen));
-        } else {
-            str.append(name.type, name.typeLen);
-        }
-    }
-    if (name.name8 != NULL || name.name != NULL) {
-        if (str.size() > 0) {
-            char16_t div = '/';
-            str.append(&div, 1);
-        }
-        if (name.name8 != NULL) {
-            str.append(String16(name.name8, name.nameLen));
-        } else {
-            str.append(name.name, name.nameLen);
-        }
-    }
-
-    return env->NewString((const jchar*)str.string(), str.size());
-}
-
-static jstring android_content_AssetManager_getResourcePackageName(JNIEnv* env, jobject clazz,
-                                                                   jint resid)
-{
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return NULL;
-    }
-
-    ResTable::resource_name name;
-    if (!am->getResources().getResourceName(resid, true, &name)) {
-        return NULL;
-    }
-
-    if (name.package != NULL) {
-        return env->NewString((const jchar*)name.package, name.packageLen);
-    }
-
-    return NULL;
-}
-
-static jstring android_content_AssetManager_getResourceTypeName(JNIEnv* env, jobject clazz,
-                                                                jint resid)
-{
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return NULL;
-    }
-
-    ResTable::resource_name name;
-    if (!am->getResources().getResourceName(resid, true, &name)) {
-        return NULL;
-    }
-
-    if (name.type8 != NULL) {
-        return env->NewStringUTF(name.type8);
-    }
-
-    if (name.type != NULL) {
-        return env->NewString((const jchar*)name.type, name.typeLen);
-    }
-
-    return NULL;
-}
-
-static jstring android_content_AssetManager_getResourceEntryName(JNIEnv* env, jobject clazz,
-                                                                 jint resid)
-{
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return NULL;
-    }
-
-    ResTable::resource_name name;
-    if (!am->getResources().getResourceName(resid, true, &name)) {
-        return NULL;
-    }
-
-    if (name.name8 != NULL) {
-        return env->NewStringUTF(name.name8);
-    }
-
-    if (name.name != NULL) {
-        return env->NewString((const jchar*)name.name, name.nameLen);
-    }
-
-    return NULL;
-}
-
-static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz,
-                                                           jint ident,
-                                                           jshort density,
-                                                           jobject outValue,
-                                                           jboolean resolve)
-{
-    if (outValue == NULL) {
-         jniThrowNullPointerException(env, "outValue");
-         return 0;
-    }
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return 0;
-    }
-    const ResTable& res(am->getResources());
-
-    Res_value value;
-    ResTable_config config;
-    uint32_t typeSpecFlags;
-    ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config);
-    if (kThrowOnBadId) {
-        if (block == BAD_INDEX) {
-            jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
-            return 0;
-        }
-    }
-    uint32_t ref = ident;
-    if (resolve) {
-        block = res.resolveReference(&value, block, &ref, &typeSpecFlags, &config);
-        if (kThrowOnBadId) {
-            if (block == BAD_INDEX) {
-                jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
-                return 0;
-            }
-        }
-    }
-    if (block >= 0) {
-        return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags, &config);
-    }
-
-    return static_cast<jint>(block);
-}
-
-static jint android_content_AssetManager_loadResourceBagValue(JNIEnv* env, jobject clazz,
-                                                           jint ident, jint bagEntryId,
-                                                           jobject outValue, jboolean resolve)
-{
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return 0;
-    }
-    const ResTable& res(am->getResources());
-
-    // Now lock down the resource object and start pulling stuff from it.
-    res.lock();
-
-    ssize_t block = -1;
-    Res_value value;
-
-    const ResTable::bag_entry* entry = NULL;
-    uint32_t typeSpecFlags;
-    ssize_t entryCount = res.getBagLocked(ident, &entry, &typeSpecFlags);
-
-    for (ssize_t i=0; i<entryCount; i++) {
-        if (((uint32_t)bagEntryId) == entry->map.name.ident) {
-            block = entry->stringBlock;
-            value = entry->map.value;
-        }
-        entry++;
-    }
-
-    res.unlock();
-
-    if (block < 0) {
-        return static_cast<jint>(block);
-    }
-
-    uint32_t ref = ident;
-    if (resolve) {
-        block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
-        if (kThrowOnBadId) {
-            if (block == BAD_INDEX) {
-                jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
-                return 0;
-            }
-        }
-    }
-    if (block >= 0) {
-        return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags);
-    }
-
-    return static_cast<jint>(block);
-}
-
-static jint android_content_AssetManager_getStringBlockCount(JNIEnv* env, jobject clazz)
-{
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return 0;
-    }
-    return am->getResources().getTableCount();
-}
-
-static jlong android_content_AssetManager_getNativeStringBlock(JNIEnv* env, jobject clazz,
-                                                           jint block)
-{
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return 0;
-    }
-    return reinterpret_cast<jlong>(am->getResources().getTableStringBlock(block));
-}
-
-static jstring android_content_AssetManager_getCookieName(JNIEnv* env, jobject clazz,
-                                                       jint cookie)
-{
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return NULL;
-    }
-    String8 name(am->getAssetPath(static_cast<int32_t>(cookie)));
-    if (name.length() == 0) {
-        jniThrowException(env, "java/lang/IndexOutOfBoundsException", "Empty cookie name");
-        return NULL;
-    }
-    jstring str = env->NewStringUTF(name.string());
-    return str;
-}
-
-static jobject android_content_AssetManager_getAssignedPackageIdentifiers(JNIEnv* env, jobject clazz)
-{
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return 0;
-    }
-
-    const ResTable& res = am->getResources();
-
-    jobject sparseArray = env->NewObject(gSparseArrayOffsets.classObject,
-            gSparseArrayOffsets.constructor);
-    const size_t N = res.getBasePackageCount();
-    for (size_t i = 0; i < N; i++) {
-        const String16 name = res.getBasePackageName(i);
-        env->CallVoidMethod(
-            sparseArray, gSparseArrayOffsets.put,
-            static_cast<jint>(res.getBasePackageId(i)),
-            env->NewString(reinterpret_cast<const jchar*>(name.string()),
-                           name.size()));
-    }
-    return sparseArray;
-}
-
-static jlong android_content_AssetManager_newTheme(JNIEnv* env, jobject clazz)
-{
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return 0;
-    }
-    return reinterpret_cast<jlong>(new ResTable::Theme(am->getResources()));
-}
-
-static void android_content_AssetManager_deleteTheme(JNIEnv* env, jobject clazz,
-                                                     jlong themeHandle)
-{
-    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
-    delete theme;
-}
-
-static void android_content_AssetManager_applyThemeStyle(JNIEnv* env, jobject clazz,
-                                                         jlong themeHandle,
-                                                         jint styleRes,
-                                                         jboolean force)
-{
-    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
-    theme->applyStyle(styleRes, force ? true : false);
-}
-
-static void android_content_AssetManager_copyTheme(JNIEnv* env, jobject clazz,
-                                                   jlong destHandle, jlong srcHandle)
-{
-    ResTable::Theme* dest = reinterpret_cast<ResTable::Theme*>(destHandle);
-    ResTable::Theme* src = reinterpret_cast<ResTable::Theme*>(srcHandle);
-    dest->setTo(*src);
-}
-
-static void android_content_AssetManager_clearTheme(JNIEnv* env, jobject clazz, jlong themeHandle)
-{
-    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
-    theme->clear();
-}
-
-static jint android_content_AssetManager_loadThemeAttributeValue(
-    JNIEnv* env, jobject clazz, jlong themeHandle, jint ident, jobject outValue, jboolean resolve)
-{
-    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
-    const ResTable& res(theme->getResTable());
-
-    Res_value value;
-    // XXX value could be different in different configs!
-    uint32_t typeSpecFlags = 0;
-    ssize_t block = theme->getAttribute(ident, &value, &typeSpecFlags);
-    uint32_t ref = 0;
-    if (resolve) {
-        block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
-        if (kThrowOnBadId) {
-            if (block == BAD_INDEX) {
-                jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
-                return 0;
-            }
-        }
-    }
-    return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags) : block;
-}
-
-static jint android_content_AssetManager_getThemeChangingConfigurations(JNIEnv* env, jobject clazz,
-                                                                        jlong themeHandle)
-{
-    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
-    return theme->getChangingConfigurations();
-}
-
-static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
-                                                   jlong themeHandle, jint pri,
-                                                   jstring tag, jstring prefix)
-{
-    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
-    const ResTable& res(theme->getResTable());
-    (void)res;
-
-    // XXX Need to use params.
-    theme->dumpToLog();
-}
-
-static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject clazz,
-                                                          jlong themeToken,
-                                                          jint defStyleAttr,
-                                                          jint defStyleRes,
-                                                          jintArray inValues,
-                                                          jintArray attrs,
-                                                          jintArray outValues,
-                                                          jintArray outIndices)
-{
-    if (themeToken == 0) {
-        jniThrowNullPointerException(env, "theme token");
-        return JNI_FALSE;
-    }
-    if (attrs == NULL) {
-        jniThrowNullPointerException(env, "attrs");
-        return JNI_FALSE;
-    }
-    if (outValues == NULL) {
-        jniThrowNullPointerException(env, "out values");
-        return JNI_FALSE;
-    }
-
-    const jsize NI = env->GetArrayLength(attrs);
-    const jsize NV = env->GetArrayLength(outValues);
-    if (NV < (NI*STYLE_NUM_ENTRIES)) {
-        jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
-        return JNI_FALSE;
-    }
-
-    jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
-    if (src == NULL) {
-        return JNI_FALSE;
-    }
-
-    jint* srcValues = (jint*)env->GetPrimitiveArrayCritical(inValues, 0);
-    const jsize NSV = srcValues == NULL ? 0 : env->GetArrayLength(inValues);
-
-    jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
-    if (baseDest == NULL) {
-        env->ReleasePrimitiveArrayCritical(attrs, src, 0);
-        return JNI_FALSE;
-    }
-
-    jint* indices = NULL;
-    if (outIndices != NULL) {
-        if (env->GetArrayLength(outIndices) > NI) {
-            indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
-        }
-    }
-
-    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
-    bool result = ResolveAttrs(theme, defStyleAttr, defStyleRes,
-                               (uint32_t*) srcValues, NSV,
-                               (uint32_t*) src, NI,
-                               (uint32_t*) baseDest,
-                               (uint32_t*) indices);
-
-    if (indices != NULL) {
-        env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
-    }
-    env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
-    env->ReleasePrimitiveArrayCritical(inValues, srcValues, 0);
-    env->ReleasePrimitiveArrayCritical(attrs, src, 0);
-    return result ? JNI_TRUE : JNI_FALSE;
-}
-
-static void android_content_AssetManager_applyStyle(JNIEnv* env, jobject, jlong themeToken,
-        jint defStyleAttr, jint defStyleRes, jlong xmlParserToken, jintArray attrsObj, jint length,
-        jlong outValuesAddress, jlong outIndicesAddress) {
-    jint* attrs = env->GetIntArrayElements(attrsObj, 0);
-    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
-    ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
-    uint32_t* outValues = reinterpret_cast<uint32_t*>(static_cast<uintptr_t>(outValuesAddress));
-    uint32_t* outIndices = reinterpret_cast<uint32_t*>(static_cast<uintptr_t>(outIndicesAddress));
-    ApplyStyle(theme, xmlParser, defStyleAttr, defStyleRes,
-            reinterpret_cast<const uint32_t*>(attrs), length, outValues, outIndices);
-    env->ReleaseIntArrayElements(attrsObj, attrs, JNI_ABORT);
-}
-
-static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
-                                                        jlong xmlParserToken,
-                                                        jintArray attrs,
-                                                        jintArray outValues,
-                                                        jintArray outIndices)
-{
-    if (xmlParserToken == 0) {
-        jniThrowNullPointerException(env, "xmlParserToken");
-        return JNI_FALSE;
-    }
-    if (attrs == NULL) {
-        jniThrowNullPointerException(env, "attrs");
-        return JNI_FALSE;
-    }
-    if (outValues == NULL) {
-        jniThrowNullPointerException(env, "out values");
-        return JNI_FALSE;
-    }
-
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return JNI_FALSE;
-    }
-    const ResTable& res(am->getResources());
-    ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
-
-    const jsize NI = env->GetArrayLength(attrs);
-    const jsize NV = env->GetArrayLength(outValues);
-    if (NV < (NI*STYLE_NUM_ENTRIES)) {
-        jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
-        return JNI_FALSE;
-    }
-
-    jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
-    if (src == NULL) {
-        return JNI_FALSE;
-    }
-
-    jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
-    if (baseDest == NULL) {
-        env->ReleasePrimitiveArrayCritical(attrs, src, 0);
-        return JNI_FALSE;
-    }
-
-    jint* indices = NULL;
-    if (outIndices != NULL) {
-        if (env->GetArrayLength(outIndices) > NI) {
-            indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
-        }
-    }
-
-    bool result = RetrieveAttributes(&res, xmlParser,
-                                     (uint32_t*) src, NI,
-                                     (uint32_t*) baseDest,
-                                     (uint32_t*) indices);
-
-    if (indices != NULL) {
-        env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
-    }
-    env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
-    env->ReleasePrimitiveArrayCritical(attrs, src, 0);
-    return result ? JNI_TRUE : JNI_FALSE;
-}
-
-static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
-                                                       jint id)
-{
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return 0;
-    }
-    const ResTable& res(am->getResources());
-
-    res.lock();
-    const ResTable::bag_entry* defStyleEnt = NULL;
-    ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
-    res.unlock();
-
-    return static_cast<jint>(bagOff);
-}
-
-static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
-                                                        jint id,
-                                                        jintArray outValues)
-{
-    if (outValues == NULL) {
-        jniThrowNullPointerException(env, "out values");
-        return JNI_FALSE;
-    }
-
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return JNI_FALSE;
-    }
-    const ResTable& res(am->getResources());
-    ResTable_config config;
-    Res_value value;
-    ssize_t block;
-
-    const jsize NV = env->GetArrayLength(outValues);
-
-    jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
-    jint* dest = baseDest;
-    if (dest == NULL) {
-        jniThrowException(env, "java/lang/OutOfMemoryError", "");
-        return JNI_FALSE;
-    }
-
-    // Now lock down the resource object and start pulling stuff from it.
-    res.lock();
-
-    const ResTable::bag_entry* arrayEnt = NULL;
-    uint32_t arrayTypeSetFlags = 0;
-    ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
-    const ResTable::bag_entry* endArrayEnt = arrayEnt +
-        (bagOff >= 0 ? bagOff : 0);
-
-    int i = 0;
-    uint32_t typeSetFlags;
-    while (i < NV && arrayEnt < endArrayEnt) {
-        block = arrayEnt->stringBlock;
-        typeSetFlags = arrayTypeSetFlags;
-        config.density = 0;
-        value = arrayEnt->map.value;
-
-        uint32_t resid = 0;
-        if (value.dataType != Res_value::TYPE_NULL) {
-            // Take care of resolving the found resource to its final value.
-            //printf("Resolving attribute reference\n");
-            ssize_t newBlock = res.resolveReference(&value, block, &resid,
-                    &typeSetFlags, &config);
-            if (kThrowOnBadId) {
-                if (newBlock == BAD_INDEX) {
-                    jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
-                    return JNI_FALSE;
-                }
-            }
-            if (newBlock >= 0) block = newBlock;
-        }
-
-        // Deal with the special @null value -- it turns back to TYPE_NULL.
-        if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
-            value.dataType = Res_value::TYPE_NULL;
-            value.data = Res_value::DATA_NULL_UNDEFINED;
-        }
-
-        //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
-
-        // Write the final value back to Java.
-        dest[STYLE_TYPE] = value.dataType;
-        dest[STYLE_DATA] = value.data;
-        dest[STYLE_ASSET_COOKIE] = reinterpret_cast<jint>(res.getTableCookie(block));
-        dest[STYLE_RESOURCE_ID] = resid;
-        dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
-        dest[STYLE_DENSITY] = config.density;
-        dest += STYLE_NUM_ENTRIES;
-        i+= STYLE_NUM_ENTRIES;
-        arrayEnt++;
-    }
-
-    i /= STYLE_NUM_ENTRIES;
-
-    res.unlock();
-
-    env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
-
-    return i;
-}
-
-static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
-                                                         jint cookie,
-                                                         jstring fileName)
-{
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return 0;
-    }
-
-    ALOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
-
-    ScopedUtfChars fileName8(env, fileName);
-    if (fileName8.c_str() == NULL) {
-        return 0;
-    }
-
-    int32_t assetCookie = static_cast<int32_t>(cookie);
-    Asset* a = assetCookie
-        ? am->openNonAsset(assetCookie, fileName8.c_str(), Asset::ACCESS_BUFFER)
-        : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER, &assetCookie);
-
-    if (a == NULL) {
-        jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
-        return 0;
-    }
-
-    const DynamicRefTable* dynamicRefTable =
-            am->getResources().getDynamicRefTableForCookie(assetCookie);
-    ResXMLTree* block = new ResXMLTree(dynamicRefTable);
-    status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
-    a->close();
-    delete a;
-
-    if (err != NO_ERROR) {
-        jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
-        return 0;
-    }
-
-    return reinterpret_cast<jlong>(block);
-}
-
-static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
-                                                                 jint arrayResId)
-{
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return NULL;
-    }
-    const ResTable& res(am->getResources());
-
-    const ResTable::bag_entry* startOfBag;
-    const ssize_t N = res.lockBag(arrayResId, &startOfBag);
-    if (N < 0) {
-        return NULL;
-    }
-
-    jintArray array = env->NewIntArray(N * 2);
-    if (array == NULL) {
-        res.unlockBag(startOfBag);
-        return NULL;
-    }
-
-    Res_value value;
-    const ResTable::bag_entry* bag = startOfBag;
-    for (size_t i = 0, j = 0; ((ssize_t)i)<N; i++, bag++) {
-        jint stringIndex = -1;
-        jint stringBlock = 0;
-        value = bag->map.value;
-
-        // Take care of resolving the found resource to its final value.
-        stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
-        if (value.dataType == Res_value::TYPE_STRING) {
-            stringIndex = value.data;
-        }
-
-        if (kThrowOnBadId) {
-            if (stringBlock == BAD_INDEX) {
-                jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
-                return array;
-            }
-        }
-
-        //todo: It might be faster to allocate a C array to contain
-        //      the blocknums and indices, put them in there and then
-        //      do just one SetIntArrayRegion()
-        env->SetIntArrayRegion(array, j, 1, &stringBlock);
-        env->SetIntArrayRegion(array, j + 1, 1, &stringIndex);
-        j = j + 2;
-    }
-    res.unlockBag(startOfBag);
-    return array;
-}
-
-static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* env, jobject clazz,
-                                                                        jint arrayResId)
-{
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return NULL;
-    }
-    const ResTable& res(am->getResources());
-
-    const ResTable::bag_entry* startOfBag;
-    const ssize_t N = res.lockBag(arrayResId, &startOfBag);
-    if (N < 0) {
-        return NULL;
-    }
-
-    jobjectArray array = env->NewObjectArray(N, g_stringClass, NULL);
-    if (env->ExceptionCheck()) {
-        res.unlockBag(startOfBag);
-        return NULL;
-    }
-
-    Res_value value;
-    const ResTable::bag_entry* bag = startOfBag;
-    size_t strLen = 0;
-    for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
-        value = bag->map.value;
-        jstring str = NULL;
-
-        // Take care of resolving the found resource to its final value.
-        ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
-        if (kThrowOnBadId) {
-            if (block == BAD_INDEX) {
-                jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
-                return array;
-            }
-        }
-        if (value.dataType == Res_value::TYPE_STRING) {
-            const ResStringPool* pool = res.getTableStringBlock(block);
-            const char* str8 = pool->string8At(value.data, &strLen);
-            if (str8 != NULL) {
-                str = env->NewStringUTF(str8);
-            } else {
-                const char16_t* str16 = pool->stringAt(value.data, &strLen);
-                str = env->NewString(reinterpret_cast<const jchar*>(str16),
-                                     strLen);
-            }
-
-            // If one of our NewString{UTF} calls failed due to memory, an
-            // exception will be pending.
-            if (env->ExceptionCheck()) {
-                res.unlockBag(startOfBag);
-                return NULL;
-            }
-
-            env->SetObjectArrayElement(array, i, str);
-
-            // str is not NULL at that point, otherwise ExceptionCheck would have been true.
-            // If we have a large amount of strings in our array, we might
-            // overflow the local reference table of the VM.
-            env->DeleteLocalRef(str);
-        }
-    }
-    res.unlockBag(startOfBag);
-    return array;
-}
-
-static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, jobject clazz,
-                                                                        jint arrayResId)
-{
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return NULL;
-    }
-    const ResTable& res(am->getResources());
-
-    const ResTable::bag_entry* startOfBag;
-    const ssize_t N = res.lockBag(arrayResId, &startOfBag);
-    if (N < 0) {
-        return NULL;
-    }
-
-    jintArray array = env->NewIntArray(N);
-    if (array == NULL) {
-        res.unlockBag(startOfBag);
-        return NULL;
-    }
-
-    Res_value value;
-    const ResTable::bag_entry* bag = startOfBag;
-    for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
-        value = bag->map.value;
-
-        // Take care of resolving the found resource to its final value.
-        ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
-        if (kThrowOnBadId) {
-            if (block == BAD_INDEX) {
-                jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
-                return array;
-            }
-        }
-        if (value.dataType >= Res_value::TYPE_FIRST_INT
-                && value.dataType <= Res_value::TYPE_LAST_INT) {
-            int intVal = value.data;
-            env->SetIntArrayRegion(array, i, 1, &intVal);
-        }
-    }
-    res.unlockBag(startOfBag);
-    return array;
-}
-
-static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jobject clazz,
-                                                                 jint styleId)
-{
-    AssetManager* am = assetManagerForJavaObject(env, clazz);
-    if (am == NULL) {
-        return NULL;
-    }
-    const ResTable& res(am->getResources());
-
-    const ResTable::bag_entry* startOfBag;
-    const ssize_t N = res.lockBag(styleId, &startOfBag);
-    if (N < 0) {
-        return NULL;
-    }
-
-    jintArray array = env->NewIntArray(N);
-    if (array == NULL) {
-        res.unlockBag(startOfBag);
-        return NULL;
-    }
-
-    const ResTable::bag_entry* bag = startOfBag;
-    for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
-        int resourceId = bag->map.name.ident;
-        env->SetIntArrayRegion(array, i, 1, &resourceId);
-    }
-    res.unlockBag(startOfBag);
-    return array;
-}
-
-static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
-{
-    if (isSystem) {
-        verifySystemIdmaps();
-    }
-    AssetManager* am = new AssetManager();
-    if (am == NULL) {
-        jniThrowException(env, "java/lang/OutOfMemoryError", "");
-        return;
-    }
-
-    am->addDefaultAssets();
-
-    ALOGV("Created AssetManager %p for Java object %p\n", am, clazz);
-    env->SetLongField(clazz, gAssetManagerOffsets.mObject, reinterpret_cast<jlong>(am));
-}
-
-static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
-{
-    AssetManager* am = (AssetManager*)
-        (env->GetLongField(clazz, gAssetManagerOffsets.mObject));
-    ALOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
-    if (am != NULL) {
-        delete am;
-        env->SetLongField(clazz, gAssetManagerOffsets.mObject, 0);
-    }
-}
-
-static jint android_content_AssetManager_getGlobalAssetCount(JNIEnv* env, jobject clazz)
-{
-    return Asset::getGlobalCount();
-}
-
-static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
-{
-    String8 alloc = Asset::getAssetAllocations();
-    if (alloc.length() <= 0) {
-        return NULL;
-    }
-
-    jstring str = env->NewStringUTF(alloc.string());
-    return str;
-}
-
-static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
-{
-    return AssetManager::getGlobalCount();
+static jint CopyValue(JNIEnv* env, ApkAssetsCookie cookie, const Res_value& value, uint32_t ref,
+                      uint32_t type_spec_flags, ResTable_config* config, jobject out_typed_value) {
+  env->SetIntField(out_typed_value, gTypedValueOffsets.mType, value.dataType);
+  env->SetIntField(out_typed_value, gTypedValueOffsets.mAssetCookie,
+                   ApkAssetsCookieToJavaCookie(cookie));
+  env->SetIntField(out_typed_value, gTypedValueOffsets.mData, value.data);
+  env->SetObjectField(out_typed_value, gTypedValueOffsets.mString, nullptr);
+  env->SetIntField(out_typed_value, gTypedValueOffsets.mResourceId, ref);
+  env->SetIntField(out_typed_value, gTypedValueOffsets.mChangingConfigurations, type_spec_flags);
+  if (config != nullptr) {
+    env->SetIntField(out_typed_value, gTypedValueOffsets.mDensity, config->density);
+  }
+  return static_cast<jint>(ApkAssetsCookieToJavaCookie(cookie));
 }
 
 // ----------------------------------------------------------------------------
 
-/*
- * JNI registration.
- */
-static const JNINativeMethod gAssetManagerMethods[] = {
-    /* name, signature, funcPtr */
-
-    // Basic asset stuff.
-    { "openAsset",      "(Ljava/lang/String;I)J",
-        (void*) android_content_AssetManager_openAsset },
-    { "openAssetFd",      "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
-        (void*) android_content_AssetManager_openAssetFd },
-    { "openNonAssetNative", "(ILjava/lang/String;I)J",
-        (void*) android_content_AssetManager_openNonAssetNative },
-    { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
-        (void*) android_content_AssetManager_openNonAssetFdNative },
-    { "list",           "(Ljava/lang/String;)[Ljava/lang/String;",
-        (void*) android_content_AssetManager_list },
-    { "destroyAsset",   "(J)V",
-        (void*) android_content_AssetManager_destroyAsset },
-    { "readAssetChar",  "(J)I",
-        (void*) android_content_AssetManager_readAssetChar },
-    { "readAsset",      "(J[BII)I",
-        (void*) android_content_AssetManager_readAsset },
-    { "seekAsset",      "(JJI)J",
-        (void*) android_content_AssetManager_seekAsset },
-    { "getAssetLength", "(J)J",
-        (void*) android_content_AssetManager_getAssetLength },
-    { "getAssetRemainingLength", "(J)J",
-        (void*) android_content_AssetManager_getAssetRemainingLength },
-    { "addAssetPathNative", "(Ljava/lang/String;Z)I",
-        (void*) android_content_AssetManager_addAssetPath },
-    { "addAssetFdNative", "(Ljava/io/FileDescriptor;Ljava/lang/String;Z)I",
-        (void*) android_content_AssetManager_addAssetFd },
-    { "addOverlayPathNative",   "(Ljava/lang/String;)I",
-        (void*) android_content_AssetManager_addOverlayPath },
-    { "isUpToDate",     "()Z",
-        (void*) android_content_AssetManager_isUpToDate },
-
-    // Resources.
-    { "getLocales",      "()[Ljava/lang/String;",
-        (void*) android_content_AssetManager_getLocales },
-    { "getNonSystemLocales", "()[Ljava/lang/String;",
-        (void*) android_content_AssetManager_getNonSystemLocales },
-    { "getSizeConfigurations", "()[Landroid/content/res/Configuration;",
-        (void*) android_content_AssetManager_getSizeConfigurations },
-    { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIIII)V",
-        (void*) android_content_AssetManager_setConfiguration },
-    { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
-        (void*) android_content_AssetManager_getResourceIdentifier },
-    { "getResourceName","(I)Ljava/lang/String;",
-        (void*) android_content_AssetManager_getResourceName },
-    { "getResourcePackageName","(I)Ljava/lang/String;",
-        (void*) android_content_AssetManager_getResourcePackageName },
-    { "getResourceTypeName","(I)Ljava/lang/String;",
-        (void*) android_content_AssetManager_getResourceTypeName },
-    { "getResourceEntryName","(I)Ljava/lang/String;",
-        (void*) android_content_AssetManager_getResourceEntryName },
-    { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
-        (void*) android_content_AssetManager_loadResourceValue },
-    { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
-        (void*) android_content_AssetManager_loadResourceBagValue },
-    { "getStringBlockCount","()I",
-        (void*) android_content_AssetManager_getStringBlockCount },
-    { "getNativeStringBlock","(I)J",
-        (void*) android_content_AssetManager_getNativeStringBlock },
-    { "getCookieName","(I)Ljava/lang/String;",
-        (void*) android_content_AssetManager_getCookieName },
-    { "getAssignedPackageIdentifiers","()Landroid/util/SparseArray;",
-        (void*) android_content_AssetManager_getAssignedPackageIdentifiers },
-
-    // Themes.
-    { "newTheme", "()J",
-        (void*) android_content_AssetManager_newTheme },
-    { "deleteTheme", "(J)V",
-        (void*) android_content_AssetManager_deleteTheme },
-    { "applyThemeStyle", "(JIZ)V",
-        (void*) android_content_AssetManager_applyThemeStyle },
-    { "copyTheme", "(JJ)V",
-        (void*) android_content_AssetManager_copyTheme },
-    { "clearTheme", "(J)V",
-        (void*) android_content_AssetManager_clearTheme },
-    { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
-        (void*) android_content_AssetManager_loadThemeAttributeValue },
-    { "getThemeChangingConfigurations", "(J)I",
-        (void*) android_content_AssetManager_getThemeChangingConfigurations },
-    { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
-        (void*) android_content_AssetManager_dumpTheme },
-    { "applyStyle","(JIIJ[IIJJ)V",
-        (void*) android_content_AssetManager_applyStyle },
-    { "resolveAttrs","(JII[I[I[I[I)Z",
-        (void*) android_content_AssetManager_resolveAttrs },
-    { "retrieveAttributes","(J[I[I[I)Z",
-        (void*) android_content_AssetManager_retrieveAttributes },
-    { "getArraySize","(I)I",
-        (void*) android_content_AssetManager_getArraySize },
-    { "retrieveArray","(I[I)I",
-        (void*) android_content_AssetManager_retrieveArray },
-
-    // XML files.
-    { "openXmlAssetNative", "(ILjava/lang/String;)J",
-        (void*) android_content_AssetManager_openXmlAssetNative },
-
-    // Arrays.
-    { "getArrayStringResource","(I)[Ljava/lang/String;",
-        (void*) android_content_AssetManager_getArrayStringResource },
-    { "getArrayStringInfo","(I)[I",
-        (void*) android_content_AssetManager_getArrayStringInfo },
-    { "getArrayIntResource","(I)[I",
-        (void*) android_content_AssetManager_getArrayIntResource },
-    { "getStyleAttributes","(I)[I",
-        (void*) android_content_AssetManager_getStyleAttributes },
-
-    // Bookkeeping.
-    { "init",           "(Z)V",
-        (void*) android_content_AssetManager_init },
-    { "destroy",        "()V",
-        (void*) android_content_AssetManager_destroy },
-    { "getGlobalAssetCount", "()I",
-        (void*) android_content_AssetManager_getGlobalAssetCount },
-    { "getAssetAllocations", "()Ljava/lang/String;",
-        (void*) android_content_AssetManager_getAssetAllocations },
-    { "getGlobalAssetManagerCount", "()I",
-        (void*) android_content_AssetManager_getGlobalAssetManagerCount },
+// Let the opaque type AAssetManager refer to a guarded AssetManager2 instance.
+struct GuardedAssetManager : public ::AAssetManager {
+  Guarded<AssetManager2> guarded_assetmanager;
 };
 
-int register_android_content_AssetManager(JNIEnv* env)
-{
-    jclass typedValue = FindClassOrDie(env, "android/util/TypedValue");
-    gTypedValueOffsets.mType = GetFieldIDOrDie(env, typedValue, "type", "I");
-    gTypedValueOffsets.mData = GetFieldIDOrDie(env, typedValue, "data", "I");
-    gTypedValueOffsets.mString = GetFieldIDOrDie(env, typedValue, "string",
-                                                 "Ljava/lang/CharSequence;");
-    gTypedValueOffsets.mAssetCookie = GetFieldIDOrDie(env, typedValue, "assetCookie", "I");
-    gTypedValueOffsets.mResourceId = GetFieldIDOrDie(env, typedValue, "resourceId", "I");
-    gTypedValueOffsets.mChangingConfigurations = GetFieldIDOrDie(env, typedValue,
-                                                                 "changingConfigurations", "I");
-    gTypedValueOffsets.mDensity = GetFieldIDOrDie(env, typedValue, "density", "I");
+::AAssetManager* NdkAssetManagerForJavaObject(JNIEnv* env, jobject jassetmanager) {
+  jlong assetmanager_handle = env->GetLongField(jassetmanager, gAssetManagerOffsets.mObject);
+  ::AAssetManager* am = reinterpret_cast<::AAssetManager*>(assetmanager_handle);
+  if (am == nullptr) {
+    jniThrowException(env, "java/lang/IllegalStateException", "AssetManager has been finalized!");
+    return nullptr;
+  }
+  return am;
+}
 
-    jclass assetFd = FindClassOrDie(env, "android/content/res/AssetFileDescriptor");
-    gAssetFileDescriptorOffsets.mFd = GetFieldIDOrDie(env, assetFd, "mFd",
-                                                      "Landroid/os/ParcelFileDescriptor;");
-    gAssetFileDescriptorOffsets.mStartOffset = GetFieldIDOrDie(env, assetFd, "mStartOffset", "J");
-    gAssetFileDescriptorOffsets.mLength = GetFieldIDOrDie(env, assetFd, "mLength", "J");
+Guarded<AssetManager2>* AssetManagerForNdkAssetManager(::AAssetManager* assetmanager) {
+  if (assetmanager == nullptr) {
+    return nullptr;
+  }
+  return &reinterpret_cast<GuardedAssetManager*>(assetmanager)->guarded_assetmanager;
+}
 
-    jclass assetManager = FindClassOrDie(env, "android/content/res/AssetManager");
-    gAssetManagerOffsets.mObject = GetFieldIDOrDie(env, assetManager, "mObject", "J");
+Guarded<AssetManager2>* AssetManagerForJavaObject(JNIEnv* env, jobject jassetmanager) {
+  return AssetManagerForNdkAssetManager(NdkAssetManagerForJavaObject(env, jassetmanager));
+}
 
-    jclass stringClass = FindClassOrDie(env, "java/lang/String");
-    g_stringClass = MakeGlobalRefOrDie(env, stringClass);
+static Guarded<AssetManager2>& AssetManagerFromLong(jlong ptr) {
+  return *AssetManagerForNdkAssetManager(reinterpret_cast<AAssetManager*>(ptr));
+}
 
-    jclass sparseArrayClass = FindClassOrDie(env, "android/util/SparseArray");
-    gSparseArrayOffsets.classObject = MakeGlobalRefOrDie(env, sparseArrayClass);
-    gSparseArrayOffsets.constructor = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject,
-                                                       "<init>", "()V");
-    gSparseArrayOffsets.put = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject, "put",
-                                               "(ILjava/lang/Object;)V");
+static jobject ReturnParcelFileDescriptor(JNIEnv* env, std::unique_ptr<Asset> asset,
+                                          jlongArray out_offsets) {
+  off64_t start_offset, length;
+  int fd = asset->openFileDescriptor(&start_offset, &length);
+  asset.reset();
 
-    jclass configurationClass = FindClassOrDie(env, "android/content/res/Configuration");
-    gConfigurationOffsets.classObject = MakeGlobalRefOrDie(env, configurationClass);
-    gConfigurationOffsets.constructor = GetMethodIDOrDie(env, configurationClass,
-            "<init>", "()V");
-    gConfigurationOffsets.mSmallestScreenWidthDpOffset = GetFieldIDOrDie(env, configurationClass,
-            "smallestScreenWidthDp", "I");
-    gConfigurationOffsets.mScreenWidthDpOffset = GetFieldIDOrDie(env, configurationClass,
-            "screenWidthDp", "I");
-    gConfigurationOffsets.mScreenHeightDpOffset = GetFieldIDOrDie(env, configurationClass,
-            "screenHeightDp", "I");
+  if (fd < 0) {
+    jniThrowException(env, "java/io/FileNotFoundException",
+                      "This file can not be opened as a file descriptor; it is probably "
+                      "compressed");
+    return nullptr;
+  }
 
-    return RegisterMethodsOrDie(env, "android/content/res/AssetManager", gAssetManagerMethods,
-                                NELEM(gAssetManagerMethods));
+  jlong* offsets = reinterpret_cast<jlong*>(env->GetPrimitiveArrayCritical(out_offsets, 0));
+  if (offsets == nullptr) {
+    close(fd);
+    return nullptr;
+  }
+
+  offsets[0] = start_offset;
+  offsets[1] = length;
+
+  env->ReleasePrimitiveArrayCritical(out_offsets, offsets, 0);
+
+  jobject file_desc = jniCreateFileDescriptor(env, fd);
+  if (file_desc == nullptr) {
+    close(fd);
+    return nullptr;
+  }
+  return newParcelFileDescriptor(env, file_desc);
+}
+
+static jint NativeGetGlobalAssetCount(JNIEnv* /*env*/, jobject /*clazz*/) {
+  return Asset::getGlobalCount();
+}
+
+static jobject NativeGetAssetAllocations(JNIEnv* env, jobject /*clazz*/) {
+  String8 alloc = Asset::getAssetAllocations();
+  if (alloc.length() <= 0) {
+    return nullptr;
+  }
+  return env->NewStringUTF(alloc.string());
+}
+
+static jint NativeGetGlobalAssetManagerCount(JNIEnv* /*env*/, jobject /*clazz*/) {
+  // TODO(adamlesinski): Switch to AssetManager2.
+  return AssetManager::getGlobalCount();
+}
+
+static jlong NativeCreate(JNIEnv* /*env*/, jclass /*clazz*/) {
+  // AssetManager2 needs to be protected by a lock. To avoid cache misses, we allocate the lock and
+  // AssetManager2 in a contiguous block (GuardedAssetManager).
+  return reinterpret_cast<jlong>(new GuardedAssetManager());
+}
+
+static void NativeDestroy(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr) {
+  delete reinterpret_cast<GuardedAssetManager*>(ptr);
+}
+
+static void NativeSetApkAssets(JNIEnv* env, jclass /*clazz*/, jlong ptr,
+                               jobjectArray apk_assets_array, jboolean invalidate_caches) {
+  ATRACE_NAME("AssetManager::SetApkAssets");
+
+  const jsize apk_assets_len = env->GetArrayLength(apk_assets_array);
+  std::vector<const ApkAssets*> apk_assets;
+  apk_assets.reserve(apk_assets_len);
+  for (jsize i = 0; i < apk_assets_len; i++) {
+    jobject obj = env->GetObjectArrayElement(apk_assets_array, i);
+    if (obj == nullptr) {
+      std::string msg = StringPrintf("ApkAssets at index %d is null", i);
+      jniThrowNullPointerException(env, msg.c_str());
+      return;
+    }
+
+    jlong apk_assets_native_ptr = env->GetLongField(obj, gApkAssetsFields.native_ptr);
+    if (env->ExceptionCheck()) {
+      return;
+    }
+    apk_assets.push_back(reinterpret_cast<const ApkAssets*>(apk_assets_native_ptr));
+  }
+
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  assetmanager->SetApkAssets(apk_assets, invalidate_caches);
+}
+
+static void NativeSetConfiguration(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint mcc, jint mnc,
+                                   jstring locale, jint orientation, jint touchscreen, jint density,
+                                   jint keyboard, jint keyboard_hidden, jint navigation,
+                                   jint screen_width, jint screen_height,
+                                   jint smallest_screen_width_dp, jint screen_width_dp,
+                                   jint screen_height_dp, jint screen_layout, jint ui_mode,
+                                   jint color_mode, jint major_version) {
+  ATRACE_NAME("AssetManager::SetConfiguration");
+
+  ResTable_config configuration;
+  memset(&configuration, 0, sizeof(configuration));
+  configuration.mcc = static_cast<uint16_t>(mcc);
+  configuration.mnc = static_cast<uint16_t>(mnc);
+  configuration.orientation = static_cast<uint8_t>(orientation);
+  configuration.touchscreen = static_cast<uint8_t>(touchscreen);
+  configuration.density = static_cast<uint16_t>(density);
+  configuration.keyboard = static_cast<uint8_t>(keyboard);
+  configuration.inputFlags = static_cast<uint8_t>(keyboard_hidden);
+  configuration.navigation = static_cast<uint8_t>(navigation);
+  configuration.screenWidth = static_cast<uint16_t>(screen_width);
+  configuration.screenHeight = static_cast<uint16_t>(screen_height);
+  configuration.smallestScreenWidthDp = static_cast<uint16_t>(smallest_screen_width_dp);
+  configuration.screenWidthDp = static_cast<uint16_t>(screen_width_dp);
+  configuration.screenHeightDp = static_cast<uint16_t>(screen_height_dp);
+  configuration.screenLayout = static_cast<uint8_t>(screen_layout);
+  configuration.uiMode = static_cast<uint8_t>(ui_mode);
+  configuration.colorMode = static_cast<uint8_t>(color_mode);
+  configuration.sdkVersion = static_cast<uint16_t>(major_version);
+
+  if (locale != nullptr) {
+    ScopedUtfChars locale_utf8(env, locale);
+    CHECK(locale_utf8.c_str() != nullptr);
+    configuration.setBcp47Locale(locale_utf8.c_str());
+  }
+
+  // Constants duplicated from Java class android.content.res.Configuration.
+  static const jint kScreenLayoutRoundMask = 0x300;
+  static const jint kScreenLayoutRoundShift = 8;
+
+  // In Java, we use a 32bit integer for screenLayout, while we only use an 8bit integer
+  // in C++. We must extract the round qualifier out of the Java screenLayout and put it
+  // into screenLayout2.
+  configuration.screenLayout2 =
+      static_cast<uint8_t>((screen_layout & kScreenLayoutRoundMask) >> kScreenLayoutRoundShift);
+
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  assetmanager->SetConfiguration(configuration);
+}
+
+static jobject NativeGetAssignedPackageIdentifiers(JNIEnv* env, jclass /*clazz*/, jlong ptr) {
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+
+  jobject sparse_array =
+        env->NewObject(gSparseArrayOffsets.classObject, gSparseArrayOffsets.constructor);
+
+  if (sparse_array == nullptr) {
+    // An exception is pending.
+    return nullptr;
+  }
+
+  assetmanager->ForEachPackage([&](const std::string& package_name, uint8_t package_id) {
+    jstring jpackage_name = env->NewStringUTF(package_name.c_str());
+    if (jpackage_name == nullptr) {
+      // An exception is pending.
+      return;
+    }
+
+    env->CallVoidMethod(sparse_array, gSparseArrayOffsets.put, static_cast<jint>(package_id),
+                        jpackage_name);
+  });
+  return sparse_array;
+}
+
+static jobjectArray NativeList(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring path) {
+  ScopedUtfChars path_utf8(env, path);
+  if (path_utf8.c_str() == nullptr) {
+    // This will throw NPE.
+    return nullptr;
+  }
+
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  std::unique_ptr<AssetDir> asset_dir =
+      assetmanager->OpenDir(path_utf8.c_str());
+  if (asset_dir == nullptr) {
+    jniThrowException(env, "java/io/FileNotFoundException", path_utf8.c_str());
+    return nullptr;
+  }
+
+  const size_t file_count = asset_dir->getFileCount();
+
+  jobjectArray array = env->NewObjectArray(file_count, g_stringClass, nullptr);
+  if (array == nullptr) {
+    return nullptr;
+  }
+
+  for (size_t i = 0; i < file_count; i++) {
+    jstring java_string = env->NewStringUTF(asset_dir->getFileName(i).string());
+
+    // Check for errors creating the strings (if malformed or no memory).
+    if (env->ExceptionCheck()) {
+     return nullptr;
+    }
+
+    env->SetObjectArrayElement(array, i, java_string);
+
+    // If we have a large amount of string in our array, we might overflow the
+    // local reference table of the VM.
+    env->DeleteLocalRef(java_string);
+  }
+  return array;
+}
+
+static jlong NativeOpenAsset(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring asset_path,
+                             jint access_mode) {
+  ScopedUtfChars asset_path_utf8(env, asset_path);
+  if (asset_path_utf8.c_str() == nullptr) {
+    // This will throw NPE.
+    return 0;
+  }
+
+  ATRACE_NAME(base::StringPrintf("AssetManager::OpenAsset(%s)", asset_path_utf8.c_str()).c_str());
+
+  if (access_mode != Asset::ACCESS_UNKNOWN && access_mode != Asset::ACCESS_RANDOM &&
+      access_mode != Asset::ACCESS_STREAMING && access_mode != Asset::ACCESS_BUFFER) {
+    jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
+    return 0;
+  }
+
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  std::unique_ptr<Asset> asset =
+      assetmanager->Open(asset_path_utf8.c_str(), static_cast<Asset::AccessMode>(access_mode));
+  if (!asset) {
+    jniThrowException(env, "java/io/FileNotFoundException", asset_path_utf8.c_str());
+    return 0;
+  }
+  return reinterpret_cast<jlong>(asset.release());
+}
+
+static jobject NativeOpenAssetFd(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring asset_path,
+                                 jlongArray out_offsets) {
+  ScopedUtfChars asset_path_utf8(env, asset_path);
+  if (asset_path_utf8.c_str() == nullptr) {
+    // This will throw NPE.
+    return nullptr;
+  }
+
+  ATRACE_NAME(base::StringPrintf("AssetManager::OpenAssetFd(%s)", asset_path_utf8.c_str()).c_str());
+
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  std::unique_ptr<Asset> asset = assetmanager->Open(asset_path_utf8.c_str(), Asset::ACCESS_RANDOM);
+  if (!asset) {
+    jniThrowException(env, "java/io/FileNotFoundException", asset_path_utf8.c_str());
+    return nullptr;
+  }
+  return ReturnParcelFileDescriptor(env, std::move(asset), out_offsets);
+}
+
+static jlong NativeOpenNonAsset(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint jcookie,
+                                jstring asset_path, jint access_mode) {
+  ApkAssetsCookie cookie = JavaCookieToApkAssetsCookie(jcookie);
+  ScopedUtfChars asset_path_utf8(env, asset_path);
+  if (asset_path_utf8.c_str() == nullptr) {
+    // This will throw NPE.
+    return 0;
+  }
+
+  ATRACE_NAME(base::StringPrintf("AssetManager::OpenNonAsset(%s)", asset_path_utf8.c_str()).c_str());
+
+  if (access_mode != Asset::ACCESS_UNKNOWN && access_mode != Asset::ACCESS_RANDOM &&
+      access_mode != Asset::ACCESS_STREAMING && access_mode != Asset::ACCESS_BUFFER) {
+    jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
+    return 0;
+  }
+
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  std::unique_ptr<Asset> asset;
+  if (cookie != kInvalidCookie) {
+    asset = assetmanager->OpenNonAsset(asset_path_utf8.c_str(), cookie,
+                                       static_cast<Asset::AccessMode>(access_mode));
+  } else {
+    asset = assetmanager->OpenNonAsset(asset_path_utf8.c_str(),
+                                       static_cast<Asset::AccessMode>(access_mode));
+  }
+
+  if (!asset) {
+    jniThrowException(env, "java/io/FileNotFoundException", asset_path_utf8.c_str());
+    return 0;
+  }
+  return reinterpret_cast<jlong>(asset.release());
+}
+
+static jobject NativeOpenNonAssetFd(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint jcookie,
+                                    jstring asset_path, jlongArray out_offsets) {
+  ApkAssetsCookie cookie = JavaCookieToApkAssetsCookie(jcookie);
+  ScopedUtfChars asset_path_utf8(env, asset_path);
+  if (asset_path_utf8.c_str() == nullptr) {
+    // This will throw NPE.
+    return nullptr;
+  }
+
+  ATRACE_NAME(base::StringPrintf("AssetManager::OpenNonAssetFd(%s)", asset_path_utf8.c_str()).c_str());
+
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  std::unique_ptr<Asset> asset;
+  if (cookie != kInvalidCookie) {
+    asset = assetmanager->OpenNonAsset(asset_path_utf8.c_str(), cookie, Asset::ACCESS_RANDOM);
+  } else {
+    asset = assetmanager->OpenNonAsset(asset_path_utf8.c_str(), Asset::ACCESS_RANDOM);
+  }
+
+  if (!asset) {
+    jniThrowException(env, "java/io/FileNotFoundException", asset_path_utf8.c_str());
+    return nullptr;
+  }
+  return ReturnParcelFileDescriptor(env, std::move(asset), out_offsets);
+}
+
+static jlong NativeOpenXmlAsset(JNIEnv* env, jobject /*clazz*/, jlong ptr, jint jcookie,
+                                jstring asset_path) {
+  ApkAssetsCookie cookie = JavaCookieToApkAssetsCookie(jcookie);
+  ScopedUtfChars asset_path_utf8(env, asset_path);
+  if (asset_path_utf8.c_str() == nullptr) {
+    // This will throw NPE.
+    return 0;
+  }
+
+  ATRACE_NAME(base::StringPrintf("AssetManager::OpenXmlAsset(%s)", asset_path_utf8.c_str()).c_str());
+
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  std::unique_ptr<Asset> asset;
+  if (cookie != kInvalidCookie) {
+    asset = assetmanager->OpenNonAsset(asset_path_utf8.c_str(), cookie, Asset::ACCESS_RANDOM);
+  } else {
+    asset = assetmanager->OpenNonAsset(asset_path_utf8.c_str(), Asset::ACCESS_RANDOM, &cookie);
+  }
+
+  if (!asset) {
+    jniThrowException(env, "java/io/FileNotFoundException", asset_path_utf8.c_str());
+    return 0;
+  }
+
+  // May be nullptr.
+  const DynamicRefTable* dynamic_ref_table = assetmanager->GetDynamicRefTableForCookie(cookie);
+
+  std::unique_ptr<ResXMLTree> xml_tree = util::make_unique<ResXMLTree>(dynamic_ref_table);
+  status_t err = xml_tree->setTo(asset->getBuffer(true), asset->getLength(), true);
+  asset.reset();
+
+  if (err != NO_ERROR) {
+    jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
+    return 0;
+  }
+  return reinterpret_cast<jlong>(xml_tree.release());
+}
+
+static jint NativeGetResourceValue(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid,
+                                   jshort density, jobject typed_value,
+                                   jboolean resolve_references) {
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  Res_value value;
+  ResTable_config selected_config;
+  uint32_t flags;
+  ApkAssetsCookie cookie =
+      assetmanager->GetResource(static_cast<uint32_t>(resid), false /*may_be_bag*/,
+                                static_cast<uint16_t>(density), &value, &selected_config, &flags);
+  if (cookie == kInvalidCookie) {
+    return ApkAssetsCookieToJavaCookie(kInvalidCookie);
+  }
+
+  uint32_t ref = static_cast<uint32_t>(resid);
+  if (resolve_references) {
+    cookie = assetmanager->ResolveReference(cookie, &value, &selected_config, &flags, &ref);
+    if (cookie == kInvalidCookie) {
+      return ApkAssetsCookieToJavaCookie(kInvalidCookie);
+    }
+  }
+  return CopyValue(env, cookie, value, ref, flags, &selected_config, typed_value);
+}
+
+static jint NativeGetResourceBagValue(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid,
+                                      jint bag_entry_id, jobject typed_value) {
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  const ResolvedBag* bag = assetmanager->GetBag(static_cast<uint32_t>(resid));
+  if (bag == nullptr) {
+    return ApkAssetsCookieToJavaCookie(kInvalidCookie);
+  }
+
+  uint32_t type_spec_flags = bag->type_spec_flags;
+  ApkAssetsCookie cookie = kInvalidCookie;
+  const Res_value* bag_value = nullptr;
+  for (const ResolvedBag::Entry& entry : bag) {
+    if (entry.key == static_cast<uint32_t>(bag_entry_id)) {
+      cookie = entry.cookie;
+      bag_value = &entry.value;
+
+      // Keep searching (the old implementation did that).
+    }
+  }
+
+  if (cookie == kInvalidCookie) {
+    return ApkAssetsCookieToJavaCookie(kInvalidCookie);
+  }
+
+  Res_value value = *bag_value;
+  uint32_t ref = static_cast<uint32_t>(resid);
+  ResTable_config selected_config;
+  cookie = assetmanager->ResolveReference(cookie, &value, &selected_config, &type_spec_flags, &ref);
+  if (cookie == kInvalidCookie) {
+    return ApkAssetsCookieToJavaCookie(kInvalidCookie);
+  }
+  return CopyValue(env, cookie, value, ref, type_spec_flags, nullptr, typed_value);
+}
+
+static jintArray NativeGetStyleAttributes(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) {
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  const ResolvedBag* bag = assetmanager->GetBag(static_cast<uint32_t>(resid));
+  if (bag == nullptr) {
+    return nullptr;
+  }
+
+  jintArray array = env->NewIntArray(bag->entry_count);
+  if (env->ExceptionCheck()) {
+    return nullptr;
+  }
+
+  for (uint32_t i = 0; i < bag->entry_count; i++) {
+    jint attr_resid = bag->entries[i].key;
+    env->SetIntArrayRegion(array, i, 1, &attr_resid);
+  }
+  return array;
+}
+
+static jobjectArray NativeGetResourceStringArray(JNIEnv* env, jclass /*clazz*/, jlong ptr,
+                                                 jint resid) {
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  const ResolvedBag* bag = assetmanager->GetBag(static_cast<uint32_t>(resid));
+  if (bag == nullptr) {
+    return nullptr;
+  }
+
+  jobjectArray array = env->NewObjectArray(bag->entry_count, g_stringClass, nullptr);
+  if (array == nullptr) {
+    return nullptr;
+  }
+
+  for (uint32_t i = 0; i < bag->entry_count; i++) {
+    const ResolvedBag::Entry& entry = bag->entries[i];
+
+    // Resolve any references to their final value.
+    Res_value value = entry.value;
+    ResTable_config selected_config;
+    uint32_t flags;
+    uint32_t ref;
+    ApkAssetsCookie cookie =
+        assetmanager->ResolveReference(entry.cookie, &value, &selected_config, &flags, &ref);
+    if (cookie == kInvalidCookie) {
+      return nullptr;
+    }
+
+    if (value.dataType == Res_value::TYPE_STRING) {
+      const ApkAssets* apk_assets = assetmanager->GetApkAssets()[cookie];
+      const ResStringPool* pool = apk_assets->GetLoadedArsc()->GetStringPool();
+
+      jstring java_string = nullptr;
+      size_t str_len;
+      const char* str_utf8 = pool->string8At(value.data, &str_len);
+      if (str_utf8 != nullptr) {
+        java_string = env->NewStringUTF(str_utf8);
+      } else {
+        const char16_t* str_utf16 = pool->stringAt(value.data, &str_len);
+        java_string = env->NewString(reinterpret_cast<const jchar*>(str_utf16), str_len);
+      }
+
+      // Check for errors creating the strings (if malformed or no memory).
+      if (env->ExceptionCheck()) {
+        return nullptr;
+      }
+
+      env->SetObjectArrayElement(array, i, java_string);
+
+      // If we have a large amount of string in our array, we might overflow the
+      // local reference table of the VM.
+      env->DeleteLocalRef(java_string);
+    }
+  }
+  return array;
+}
+
+static jintArray NativeGetResourceStringArrayInfo(JNIEnv* env, jclass /*clazz*/, jlong ptr,
+                                                  jint resid) {
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  const ResolvedBag* bag = assetmanager->GetBag(static_cast<uint32_t>(resid));
+  if (bag == nullptr) {
+    return nullptr;
+  }
+
+  jintArray array = env->NewIntArray(bag->entry_count * 2);
+  if (array == nullptr) {
+    return nullptr;
+  }
+
+  jint* buffer = reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(array, nullptr));
+  if (buffer == nullptr) {
+    return nullptr;
+  }
+
+  for (size_t i = 0; i < bag->entry_count; i++) {
+    const ResolvedBag::Entry& entry = bag->entries[i];
+    Res_value value = entry.value;
+    ResTable_config selected_config;
+    uint32_t flags;
+    uint32_t ref;
+    ApkAssetsCookie cookie =
+        assetmanager->ResolveReference(entry.cookie, &value, &selected_config, &flags, &ref);
+    if (cookie == kInvalidCookie) {
+      env->ReleasePrimitiveArrayCritical(array, buffer, JNI_ABORT);
+      return nullptr;
+    }
+
+    jint string_index = -1;
+    if (value.dataType == Res_value::TYPE_STRING) {
+      string_index = static_cast<jint>(value.data);
+    }
+
+    buffer[i * 2] = ApkAssetsCookieToJavaCookie(cookie);
+    buffer[(i * 2) + 1] = string_index;
+  }
+  env->ReleasePrimitiveArrayCritical(array, buffer, 0);
+  return array;
+}
+
+static jintArray NativeGetResourceIntArray(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) {
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  const ResolvedBag* bag = assetmanager->GetBag(static_cast<uint32_t>(resid));
+  if (bag == nullptr) {
+    return nullptr;
+  }
+
+  jintArray array = env->NewIntArray(bag->entry_count);
+  if (array == nullptr) {
+    return nullptr;
+  }
+
+  jint* buffer = reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(array, nullptr));
+  if (buffer == nullptr) {
+    return nullptr;
+  }
+
+  for (size_t i = 0; i < bag->entry_count; i++) {
+    const ResolvedBag::Entry& entry = bag->entries[i];
+    Res_value value = entry.value;
+    ResTable_config selected_config;
+    uint32_t flags;
+    uint32_t ref;
+    ApkAssetsCookie cookie =
+        assetmanager->ResolveReference(entry.cookie, &value, &selected_config, &flags, &ref);
+    if (cookie == kInvalidCookie) {
+      env->ReleasePrimitiveArrayCritical(array, buffer, JNI_ABORT);
+      return nullptr;
+    }
+
+    if (value.dataType >= Res_value::TYPE_FIRST_INT && value.dataType <= Res_value::TYPE_LAST_INT) {
+      buffer[i] = static_cast<jint>(value.data);
+    }
+  }
+  env->ReleasePrimitiveArrayCritical(array, buffer, 0);
+  return array;
+}
+
+static jint NativeGetResourceArraySize(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr, jint resid) {
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  const ResolvedBag* bag = assetmanager->GetBag(static_cast<uint32_t>(resid));
+  if (bag == nullptr) {
+    return -1;
+  }
+  return static_cast<jint>(bag->entry_count);
+}
+
+static jint NativeGetResourceArray(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid,
+                                   jintArray out_data) {
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  const ResolvedBag* bag = assetmanager->GetBag(static_cast<uint32_t>(resid));
+  if (bag == nullptr) {
+    return -1;
+  }
+
+  const jsize out_data_length = env->GetArrayLength(out_data);
+  if (env->ExceptionCheck()) {
+    return -1;
+  }
+
+  if (static_cast<jsize>(bag->entry_count) > out_data_length * STYLE_NUM_ENTRIES) {
+    jniThrowException(env, "java/lang/IllegalArgumentException", "Input array is not large enough");
+    return -1;
+  }
+
+  jint* buffer = reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(out_data, nullptr));
+  if (buffer == nullptr) {
+    return -1;
+  }
+
+  jint* cursor = buffer;
+  for (size_t i = 0; i < bag->entry_count; i++) {
+    const ResolvedBag::Entry& entry = bag->entries[i];
+    Res_value value = entry.value;
+    ResTable_config selected_config;
+    selected_config.density = 0;
+    uint32_t flags = bag->type_spec_flags;
+    uint32_t ref;
+    ApkAssetsCookie cookie =
+        assetmanager->ResolveReference(entry.cookie, &value, &selected_config, &flags, &ref);
+    if (cookie == kInvalidCookie) {
+      env->ReleasePrimitiveArrayCritical(out_data, buffer, JNI_ABORT);
+      return -1;
+    }
+
+    // Deal with the special @null value -- it turns back to TYPE_NULL.
+    if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
+      value.dataType = Res_value::TYPE_NULL;
+      value.data = Res_value::DATA_NULL_UNDEFINED;
+    }
+
+    cursor[STYLE_TYPE] = static_cast<jint>(value.dataType);
+    cursor[STYLE_DATA] = static_cast<jint>(value.data);
+    cursor[STYLE_ASSET_COOKIE] = ApkAssetsCookieToJavaCookie(cookie);
+    cursor[STYLE_RESOURCE_ID] = static_cast<jint>(ref);
+    cursor[STYLE_CHANGING_CONFIGURATIONS] = static_cast<jint>(flags);
+    cursor[STYLE_DENSITY] = static_cast<jint>(selected_config.density);
+    cursor += STYLE_NUM_ENTRIES;
+  }
+  env->ReleasePrimitiveArrayCritical(out_data, buffer, 0);
+  return static_cast<jint>(bag->entry_count);
+}
+
+static jint NativeGetResourceIdentifier(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring name,
+                                        jstring def_type, jstring def_package) {
+  ScopedUtfChars name_utf8(env, name);
+  if (name_utf8.c_str() == nullptr) {
+    // This will throw NPE.
+    return 0;
+  }
+
+  std::string type;
+  if (def_type != nullptr) {
+    ScopedUtfChars type_utf8(env, def_type);
+    CHECK(type_utf8.c_str() != nullptr);
+    type = type_utf8.c_str();
+  }
+
+  std::string package;
+  if (def_package != nullptr) {
+    ScopedUtfChars package_utf8(env, def_package);
+    CHECK(package_utf8.c_str() != nullptr);
+    package = package_utf8.c_str();
+  }
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  return static_cast<jint>(assetmanager->GetResourceId(name_utf8.c_str(), type, package));
+}
+
+static jstring NativeGetResourceName(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) {
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  AssetManager2::ResourceName name;
+  if (!assetmanager->GetResourceName(static_cast<uint32_t>(resid), &name)) {
+    return nullptr;
+  }
+
+  std::string result;
+  if (name.package != nullptr) {
+    result.append(name.package, name.package_len);
+  }
+
+  if (name.type != nullptr || name.type16 != nullptr) {
+    if (!result.empty()) {
+      result += ":";
+    }
+
+    if (name.type != nullptr) {
+      result.append(name.type, name.type_len);
+    } else {
+      result += util::Utf16ToUtf8(StringPiece16(name.type16, name.type_len));
+    }
+  }
+
+  if (name.entry != nullptr || name.entry16 != nullptr) {
+    if (!result.empty()) {
+      result += "/";
+    }
+
+    if (name.entry != nullptr) {
+      result.append(name.entry, name.entry_len);
+    } else {
+      result += util::Utf16ToUtf8(StringPiece16(name.entry16, name.entry_len));
+    }
+  }
+  return env->NewStringUTF(result.c_str());
+}
+
+static jstring NativeGetResourcePackageName(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) {
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  AssetManager2::ResourceName name;
+  if (!assetmanager->GetResourceName(static_cast<uint32_t>(resid), &name)) {
+    return nullptr;
+  }
+
+  if (name.package != nullptr) {
+    return env->NewStringUTF(name.package);
+  }
+  return nullptr;
+}
+
+static jstring NativeGetResourceTypeName(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) {
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  AssetManager2::ResourceName name;
+  if (!assetmanager->GetResourceName(static_cast<uint32_t>(resid), &name)) {
+    return nullptr;
+  }
+
+  if (name.type != nullptr) {
+    return env->NewStringUTF(name.type);
+  } else if (name.type16 != nullptr) {
+    return env->NewString(reinterpret_cast<const jchar*>(name.type16), name.type_len);
+  }
+  return nullptr;
+}
+
+static jstring NativeGetResourceEntryName(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) {
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  AssetManager2::ResourceName name;
+  if (!assetmanager->GetResourceName(static_cast<uint32_t>(resid), &name)) {
+    return nullptr;
+  }
+
+  if (name.entry != nullptr) {
+    return env->NewStringUTF(name.entry);
+  } else if (name.entry16 != nullptr) {
+    return env->NewString(reinterpret_cast<const jchar*>(name.entry16), name.entry_len);
+  }
+  return nullptr;
+}
+
+static jobjectArray NativeGetLocales(JNIEnv* env, jclass /*class*/, jlong ptr,
+                                     jboolean exclude_system) {
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  std::set<std::string> locales =
+      assetmanager->GetResourceLocales(exclude_system, true /*merge_equivalent_languages*/);
+
+  jobjectArray array = env->NewObjectArray(locales.size(), g_stringClass, nullptr);
+  if (array == nullptr) {
+    return nullptr;
+  }
+
+  size_t idx = 0;
+  for (const std::string& locale : locales) {
+    jstring java_string = env->NewStringUTF(locale.c_str());
+    if (java_string == nullptr) {
+      return nullptr;
+    }
+    env->SetObjectArrayElement(array, idx++, java_string);
+    env->DeleteLocalRef(java_string);
+  }
+  return array;
+}
+
+static jobject ConstructConfigurationObject(JNIEnv* env, const ResTable_config& config) {
+  jobject result =
+      env->NewObject(gConfigurationOffsets.classObject, gConfigurationOffsets.constructor);
+  if (result == nullptr) {
+    return nullptr;
+  }
+
+  env->SetIntField(result, gConfigurationOffsets.mSmallestScreenWidthDpOffset,
+                   config.smallestScreenWidthDp);
+  env->SetIntField(result, gConfigurationOffsets.mScreenWidthDpOffset, config.screenWidthDp);
+  env->SetIntField(result, gConfigurationOffsets.mScreenHeightDpOffset, config.screenHeightDp);
+  return result;
+}
+
+static jobjectArray NativeGetSizeConfigurations(JNIEnv* env, jclass /*clazz*/, jlong ptr) {
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  std::set<ResTable_config> configurations =
+      assetmanager->GetResourceConfigurations(true /*exclude_system*/, false /*exclude_mipmap*/);
+
+  jobjectArray array =
+      env->NewObjectArray(configurations.size(), gConfigurationOffsets.classObject, nullptr);
+  if (array == nullptr) {
+    return nullptr;
+  }
+
+  size_t idx = 0;
+  for (const ResTable_config& configuration : configurations) {
+    jobject java_configuration = ConstructConfigurationObject(env, configuration);
+    if (java_configuration == nullptr) {
+      return nullptr;
+    }
+
+    env->SetObjectArrayElement(array, idx++, java_configuration);
+    env->DeleteLocalRef(java_configuration);
+  }
+  return array;
+}
+
+static void NativeApplyStyle(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr,
+                             jint def_style_attr, jint def_style_resid, jlong xml_parser_ptr,
+                             jintArray java_attrs, jlong out_values_ptr, jlong out_indices_ptr) {
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  Theme* theme = reinterpret_cast<Theme*>(theme_ptr);
+  CHECK(theme->GetAssetManager() == &(*assetmanager));
+  (void) assetmanager;
+
+  ResXMLParser* xml_parser = reinterpret_cast<ResXMLParser*>(xml_parser_ptr);
+  uint32_t* out_values = reinterpret_cast<uint32_t*>(out_values_ptr);
+  uint32_t* out_indices = reinterpret_cast<uint32_t*>(out_indices_ptr);
+
+  jsize attrs_len = env->GetArrayLength(java_attrs);
+  jint* attrs = reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(java_attrs, nullptr));
+  if (attrs == nullptr) {
+    return;
+  }
+
+  ApplyStyle(theme, xml_parser, static_cast<uint32_t>(def_style_attr),
+             static_cast<uint32_t>(def_style_resid), reinterpret_cast<uint32_t*>(attrs), attrs_len,
+             out_values, out_indices);
+  env->ReleasePrimitiveArrayCritical(java_attrs, attrs, JNI_ABORT);
+}
+
+static jboolean NativeResolveAttrs(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr,
+                                   jint def_style_attr, jint def_style_resid, jintArray java_values,
+                                   jintArray java_attrs, jintArray out_java_values,
+                                   jintArray out_java_indices) {
+  const jsize attrs_len = env->GetArrayLength(java_attrs);
+  const jsize out_values_len = env->GetArrayLength(out_java_values);
+  if (out_values_len < (attrs_len * STYLE_NUM_ENTRIES)) {
+    jniThrowException(env, "java/lang/IndexOutOfBoundsException", "outValues too small");
+    return JNI_FALSE;
+  }
+
+  jint* attrs = reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(java_attrs, nullptr));
+  if (attrs == nullptr) {
+    return JNI_FALSE;
+  }
+
+  jint* values = nullptr;
+  jsize values_len = 0;
+  if (java_values != nullptr) {
+    values_len = env->GetArrayLength(java_values);
+    values = reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(java_values, nullptr));
+    if (values == nullptr) {
+      env->ReleasePrimitiveArrayCritical(java_attrs, attrs, JNI_ABORT);
+      return JNI_FALSE;
+    }
+  }
+
+  jint* out_values =
+      reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(out_java_values, nullptr));
+  if (out_values == nullptr) {
+    env->ReleasePrimitiveArrayCritical(java_attrs, attrs, JNI_ABORT);
+    if (values != nullptr) {
+      env->ReleasePrimitiveArrayCritical(java_values, values, JNI_ABORT);
+    }
+    return JNI_FALSE;
+  }
+
+  jint* out_indices = nullptr;
+  if (out_java_indices != nullptr) {
+    jsize out_indices_len = env->GetArrayLength(out_java_indices);
+    if (out_indices_len > attrs_len) {
+      out_indices =
+          reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(out_java_indices, nullptr));
+      if (out_indices == nullptr) {
+        env->ReleasePrimitiveArrayCritical(java_attrs, attrs, JNI_ABORT);
+        if (values != nullptr) {
+          env->ReleasePrimitiveArrayCritical(java_values, values, JNI_ABORT);
+        }
+        env->ReleasePrimitiveArrayCritical(out_java_values, out_values, JNI_ABORT);
+        return JNI_FALSE;
+      }
+    }
+  }
+
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  Theme* theme = reinterpret_cast<Theme*>(theme_ptr);
+  CHECK(theme->GetAssetManager() == &(*assetmanager));
+  (void) assetmanager;
+
+  bool result = ResolveAttrs(
+      theme, static_cast<uint32_t>(def_style_attr), static_cast<uint32_t>(def_style_resid),
+      reinterpret_cast<uint32_t*>(values), values_len, reinterpret_cast<uint32_t*>(attrs),
+      attrs_len, reinterpret_cast<uint32_t*>(out_values), reinterpret_cast<uint32_t*>(out_indices));
+  if (out_indices != nullptr) {
+    env->ReleasePrimitiveArrayCritical(out_java_indices, out_indices, 0);
+  }
+
+  env->ReleasePrimitiveArrayCritical(out_java_values, out_values, 0);
+  if (values != nullptr) {
+    env->ReleasePrimitiveArrayCritical(java_values, values, JNI_ABORT);
+  }
+  env->ReleasePrimitiveArrayCritical(java_attrs, attrs, JNI_ABORT);
+  return result ? JNI_TRUE : JNI_FALSE;
+}
+
+static jboolean NativeRetrieveAttributes(JNIEnv* env, jclass /*clazz*/, jlong ptr,
+                                         jlong xml_parser_ptr, jintArray java_attrs,
+                                         jintArray out_java_values, jintArray out_java_indices) {
+  const jsize attrs_len = env->GetArrayLength(java_attrs);
+  const jsize out_values_len = env->GetArrayLength(out_java_values);
+  if (out_values_len < (attrs_len * STYLE_NUM_ENTRIES)) {
+    jniThrowException(env, "java/lang/IndexOutOfBoundsException", "outValues too small");
+    return JNI_FALSE;
+  }
+
+  jint* attrs = reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(java_attrs, nullptr));
+  if (attrs == nullptr) {
+    return JNI_FALSE;
+  }
+
+  jint* out_values =
+      reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(out_java_values, nullptr));
+  if (out_values == nullptr) {
+    env->ReleasePrimitiveArrayCritical(java_attrs, attrs, JNI_ABORT);
+    return JNI_FALSE;
+  }
+
+  jint* out_indices = nullptr;
+  if (out_java_indices != nullptr) {
+    jsize out_indices_len = env->GetArrayLength(out_java_indices);
+    if (out_indices_len > attrs_len) {
+      out_indices =
+          reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(out_java_indices, nullptr));
+      if (out_indices == nullptr) {
+        env->ReleasePrimitiveArrayCritical(java_attrs, attrs, JNI_ABORT);
+        env->ReleasePrimitiveArrayCritical(out_java_values, out_values, JNI_ABORT);
+        return JNI_FALSE;
+      }
+    }
+  }
+
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  ResXMLParser* xml_parser = reinterpret_cast<ResXMLParser*>(xml_parser_ptr);
+
+  bool result = RetrieveAttributes(assetmanager.get(), xml_parser,
+                                   reinterpret_cast<uint32_t*>(attrs), attrs_len,
+                                   reinterpret_cast<uint32_t*>(out_values),
+                                   reinterpret_cast<uint32_t*>(out_indices));
+
+  if (out_indices != nullptr) {
+    env->ReleasePrimitiveArrayCritical(out_java_indices, out_indices, 0);
+  }
+  env->ReleasePrimitiveArrayCritical(out_java_values, out_values, 0);
+  env->ReleasePrimitiveArrayCritical(java_attrs, attrs, JNI_ABORT);
+  return result ? JNI_TRUE : JNI_FALSE;
+}
+
+static jlong NativeThemeCreate(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr) {
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  return reinterpret_cast<jlong>(assetmanager->NewTheme().release());
+}
+
+static void NativeThemeDestroy(JNIEnv* /*env*/, jclass /*clazz*/, jlong theme_ptr) {
+  delete reinterpret_cast<Theme*>(theme_ptr);
+}
+
+static void NativeThemeApplyStyle(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr,
+                                  jint resid, jboolean force) {
+  // AssetManager is accessed via the theme, so grab an explicit lock here.
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  Theme* theme = reinterpret_cast<Theme*>(theme_ptr);
+  CHECK(theme->GetAssetManager() == &(*assetmanager));
+  (void) assetmanager;
+  theme->ApplyStyle(static_cast<uint32_t>(resid), force);
+
+  // TODO(adamlesinski): Consider surfacing exception when result is failure.
+  // CTS currently expects no exceptions from this method.
+  // std::string error_msg = StringPrintf("Failed to apply style 0x%08x to theme", resid);
+  // jniThrowException(env, "java/lang/IllegalArgumentException", error_msg.c_str());
+}
+
+static void NativeThemeCopy(JNIEnv* env, jclass /*clazz*/, jlong dst_theme_ptr,
+                            jlong src_theme_ptr) {
+  Theme* dst_theme = reinterpret_cast<Theme*>(dst_theme_ptr);
+  Theme* src_theme = reinterpret_cast<Theme*>(src_theme_ptr);
+  if (!dst_theme->SetTo(*src_theme)) {
+    jniThrowException(env, "java/lang/IllegalArgumentException",
+                      "Themes are from different AssetManagers");
+  }
+}
+
+static void NativeThemeClear(JNIEnv* /*env*/, jclass /*clazz*/, jlong theme_ptr) {
+  reinterpret_cast<Theme*>(theme_ptr)->Clear();
+}
+
+static jint NativeThemeGetAttributeValue(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr,
+                                         jint resid, jobject typed_value,
+                                         jboolean resolve_references) {
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  Theme* theme = reinterpret_cast<Theme*>(theme_ptr);
+  CHECK(theme->GetAssetManager() == &(*assetmanager));
+  (void) assetmanager;
+
+  Res_value value;
+  uint32_t flags;
+  ApkAssetsCookie cookie = theme->GetAttribute(static_cast<uint32_t>(resid), &value, &flags);
+  if (cookie == kInvalidCookie) {
+    return ApkAssetsCookieToJavaCookie(kInvalidCookie);
+  }
+
+  uint32_t ref = 0u;
+  if (resolve_references) {
+    ResTable_config selected_config;
+    cookie =
+        theme->GetAssetManager()->ResolveReference(cookie, &value, &selected_config, &flags, &ref);
+    if (cookie == kInvalidCookie) {
+      return ApkAssetsCookieToJavaCookie(kInvalidCookie);
+    }
+  }
+  return CopyValue(env, cookie, value, ref, flags, nullptr, typed_value);
+}
+
+static void NativeThemeDump(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr, jlong theme_ptr,
+                            jint priority, jstring tag, jstring prefix) {
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  Theme* theme = reinterpret_cast<Theme*>(theme_ptr);
+  CHECK(theme->GetAssetManager() == &(*assetmanager));
+  (void) assetmanager;
+  (void) theme;
+  (void) priority;
+  (void) tag;
+  (void) prefix;
+}
+
+static jint NativeThemeGetChangingConfigurations(JNIEnv* /*env*/, jclass /*clazz*/,
+                                                 jlong theme_ptr) {
+  Theme* theme = reinterpret_cast<Theme*>(theme_ptr);
+  return static_cast<jint>(theme->GetChangingConfigurations());
+}
+
+static void NativeAssetDestroy(JNIEnv* /*env*/, jclass /*clazz*/, jlong asset_ptr) {
+  delete reinterpret_cast<Asset*>(asset_ptr);
+}
+
+static jint NativeAssetReadChar(JNIEnv* /*env*/, jclass /*clazz*/, jlong asset_ptr) {
+  Asset* asset = reinterpret_cast<Asset*>(asset_ptr);
+  uint8_t b;
+  ssize_t res = asset->read(&b, sizeof(b));
+  return res == sizeof(b) ? static_cast<jint>(b) : -1;
+}
+
+static jint NativeAssetRead(JNIEnv* env, jclass /*clazz*/, jlong asset_ptr, jbyteArray java_buffer,
+                            jint offset, jint len) {
+  if (len == 0) {
+    return 0;
+  }
+
+  jsize buffer_len = env->GetArrayLength(java_buffer);
+  if (offset < 0 || offset >= buffer_len || len < 0 || len > buffer_len ||
+      offset > buffer_len - len) {
+    jniThrowException(env, "java/lang/IndexOutOfBoundsException", "");
+    return -1;
+  }
+
+  ScopedByteArrayRW byte_array(env, java_buffer);
+  if (byte_array.get() == nullptr) {
+    return -1;
+  }
+
+  Asset* asset = reinterpret_cast<Asset*>(asset_ptr);
+  ssize_t res = asset->read(byte_array.get() + offset, len);
+  if (res < 0) {
+    jniThrowException(env, "java/io/IOException", "");
+    return -1;
+  }
+  return res > 0 ? static_cast<jint>(res) : -1;
+}
+
+static jlong NativeAssetSeek(JNIEnv* env, jclass /*clazz*/, jlong asset_ptr, jlong offset,
+                             jint whence) {
+  Asset* asset = reinterpret_cast<Asset*>(asset_ptr);
+  return static_cast<jlong>(asset->seek(
+      static_cast<off64_t>(offset), (whence > 0 ? SEEK_END : (whence < 0 ? SEEK_SET : SEEK_CUR))));
+}
+
+static jlong NativeAssetGetLength(JNIEnv* /*env*/, jclass /*clazz*/, jlong asset_ptr) {
+  Asset* asset = reinterpret_cast<Asset*>(asset_ptr);
+  return static_cast<jlong>(asset->getLength());
+}
+
+static jlong NativeAssetGetRemainingLength(JNIEnv* /*env*/, jclass /*clazz*/, jlong asset_ptr) {
+  Asset* asset = reinterpret_cast<Asset*>(asset_ptr);
+  return static_cast<jlong>(asset->getRemainingLength());
+}
+
+// ----------------------------------------------------------------------------
+
+// JNI registration.
+static const JNINativeMethod gAssetManagerMethods[] = {
+    // AssetManager setup methods.
+    {"nativeCreate", "()J", (void*)NativeCreate},
+    {"nativeDestroy", "(J)V", (void*)NativeDestroy},
+    {"nativeSetApkAssets", "(J[Landroid/content/res/ApkAssets;Z)V", (void*)NativeSetApkAssets},
+    {"nativeSetConfiguration", "(JIILjava/lang/String;IIIIIIIIIIIIIII)V",
+     (void*)NativeSetConfiguration},
+    {"nativeGetAssignedPackageIdentifiers", "(J)Landroid/util/SparseArray;",
+     (void*)NativeGetAssignedPackageIdentifiers},
+
+    // AssetManager file methods.
+    {"nativeList", "(JLjava/lang/String;)[Ljava/lang/String;", (void*)NativeList},
+    {"nativeOpenAsset", "(JLjava/lang/String;I)J", (void*)NativeOpenAsset},
+    {"nativeOpenAssetFd", "(JLjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
+     (void*)NativeOpenAssetFd},
+    {"nativeOpenNonAsset", "(JILjava/lang/String;I)J", (void*)NativeOpenNonAsset},
+    {"nativeOpenNonAssetFd", "(JILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
+     (void*)NativeOpenNonAssetFd},
+    {"nativeOpenXmlAsset", "(JILjava/lang/String;)J", (void*)NativeOpenXmlAsset},
+
+    // AssetManager resource methods.
+    {"nativeGetResourceValue", "(JISLandroid/util/TypedValue;Z)I", (void*)NativeGetResourceValue},
+    {"nativeGetResourceBagValue", "(JIILandroid/util/TypedValue;)I",
+     (void*)NativeGetResourceBagValue},
+    {"nativeGetStyleAttributes", "(JI)[I", (void*)NativeGetStyleAttributes},
+    {"nativeGetResourceStringArray", "(JI)[Ljava/lang/String;",
+     (void*)NativeGetResourceStringArray},
+    {"nativeGetResourceStringArrayInfo", "(JI)[I", (void*)NativeGetResourceStringArrayInfo},
+    {"nativeGetResourceIntArray", "(JI)[I", (void*)NativeGetResourceIntArray},
+    {"nativeGetResourceArraySize", "(JI)I", (void*)NativeGetResourceArraySize},
+    {"nativeGetResourceArray", "(JI[I)I", (void*)NativeGetResourceArray},
+
+    // AssetManager resource name/ID methods.
+    {"nativeGetResourceIdentifier", "(JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
+     (void*)NativeGetResourceIdentifier},
+    {"nativeGetResourceName", "(JI)Ljava/lang/String;", (void*)NativeGetResourceName},
+    {"nativeGetResourcePackageName", "(JI)Ljava/lang/String;", (void*)NativeGetResourcePackageName},
+    {"nativeGetResourceTypeName", "(JI)Ljava/lang/String;", (void*)NativeGetResourceTypeName},
+    {"nativeGetResourceEntryName", "(JI)Ljava/lang/String;", (void*)NativeGetResourceEntryName},
+    {"nativeGetLocales", "(JZ)[Ljava/lang/String;", (void*)NativeGetLocales},
+    {"nativeGetSizeConfigurations", "(J)[Landroid/content/res/Configuration;",
+     (void*)NativeGetSizeConfigurations},
+
+    // Style attribute related methods.
+    {"nativeApplyStyle", "(JJIIJ[IJJ)V", (void*)NativeApplyStyle},
+    {"nativeResolveAttrs", "(JJII[I[I[I[I)Z", (void*)NativeResolveAttrs},
+    {"nativeRetrieveAttributes", "(JJ[I[I[I)Z", (void*)NativeRetrieveAttributes},
+
+    // Theme related methods.
+    {"nativeThemeCreate", "(J)J", (void*)NativeThemeCreate},
+    {"nativeThemeDestroy", "(J)V", (void*)NativeThemeDestroy},
+    {"nativeThemeApplyStyle", "(JJIZ)V", (void*)NativeThemeApplyStyle},
+    {"nativeThemeCopy", "(JJ)V", (void*)NativeThemeCopy},
+    {"nativeThemeClear", "(J)V", (void*)NativeThemeClear},
+    {"nativeThemeGetAttributeValue", "(JJILandroid/util/TypedValue;Z)I",
+     (void*)NativeThemeGetAttributeValue},
+    {"nativeThemeDump", "(JJILjava/lang/String;Ljava/lang/String;)V", (void*)NativeThemeDump},
+    {"nativeThemeGetChangingConfigurations", "(J)I", (void*)NativeThemeGetChangingConfigurations},
+
+    // AssetInputStream methods.
+    {"nativeAssetDestroy", "(J)V", (void*)NativeAssetDestroy},
+    {"nativeAssetReadChar", "(J)I", (void*)NativeAssetReadChar},
+    {"nativeAssetRead", "(J[BII)I", (void*)NativeAssetRead},
+    {"nativeAssetSeek", "(JJI)J", (void*)NativeAssetSeek},
+    {"nativeAssetGetLength", "(J)J", (void*)NativeAssetGetLength},
+    {"nativeAssetGetRemainingLength", "(J)J", (void*)NativeAssetGetRemainingLength},
+
+    // System/idmap related methods.
+    {"nativeVerifySystemIdmaps", "()V", (void*)NativeVerifySystemIdmaps},
+
+    // Global management/debug methods.
+    {"getGlobalAssetCount", "()I", (void*)NativeGetGlobalAssetCount},
+    {"getAssetAllocations", "()Ljava/lang/String;", (void*)NativeGetAssetAllocations},
+    {"getGlobalAssetManagerCount", "()I", (void*)NativeGetGlobalAssetManagerCount},
+};
+
+int register_android_content_AssetManager(JNIEnv* env) {
+  jclass apk_assets_class = FindClassOrDie(env, "android/content/res/ApkAssets");
+  gApkAssetsFields.native_ptr = GetFieldIDOrDie(env, apk_assets_class, "mNativePtr", "J");
+
+  jclass typedValue = FindClassOrDie(env, "android/util/TypedValue");
+  gTypedValueOffsets.mType = GetFieldIDOrDie(env, typedValue, "type", "I");
+  gTypedValueOffsets.mData = GetFieldIDOrDie(env, typedValue, "data", "I");
+  gTypedValueOffsets.mString =
+      GetFieldIDOrDie(env, typedValue, "string", "Ljava/lang/CharSequence;");
+  gTypedValueOffsets.mAssetCookie = GetFieldIDOrDie(env, typedValue, "assetCookie", "I");
+  gTypedValueOffsets.mResourceId = GetFieldIDOrDie(env, typedValue, "resourceId", "I");
+  gTypedValueOffsets.mChangingConfigurations =
+      GetFieldIDOrDie(env, typedValue, "changingConfigurations", "I");
+  gTypedValueOffsets.mDensity = GetFieldIDOrDie(env, typedValue, "density", "I");
+
+  jclass assetFd = FindClassOrDie(env, "android/content/res/AssetFileDescriptor");
+  gAssetFileDescriptorOffsets.mFd =
+      GetFieldIDOrDie(env, assetFd, "mFd", "Landroid/os/ParcelFileDescriptor;");
+  gAssetFileDescriptorOffsets.mStartOffset = GetFieldIDOrDie(env, assetFd, "mStartOffset", "J");
+  gAssetFileDescriptorOffsets.mLength = GetFieldIDOrDie(env, assetFd, "mLength", "J");
+
+  jclass assetManager = FindClassOrDie(env, "android/content/res/AssetManager");
+  gAssetManagerOffsets.mObject = GetFieldIDOrDie(env, assetManager, "mObject", "J");
+
+  jclass stringClass = FindClassOrDie(env, "java/lang/String");
+  g_stringClass = MakeGlobalRefOrDie(env, stringClass);
+
+  jclass sparseArrayClass = FindClassOrDie(env, "android/util/SparseArray");
+  gSparseArrayOffsets.classObject = MakeGlobalRefOrDie(env, sparseArrayClass);
+  gSparseArrayOffsets.constructor =
+      GetMethodIDOrDie(env, gSparseArrayOffsets.classObject, "<init>", "()V");
+  gSparseArrayOffsets.put =
+      GetMethodIDOrDie(env, gSparseArrayOffsets.classObject, "put", "(ILjava/lang/Object;)V");
+
+  jclass configurationClass = FindClassOrDie(env, "android/content/res/Configuration");
+  gConfigurationOffsets.classObject = MakeGlobalRefOrDie(env, configurationClass);
+  gConfigurationOffsets.constructor = GetMethodIDOrDie(env, configurationClass, "<init>", "()V");
+  gConfigurationOffsets.mSmallestScreenWidthDpOffset =
+      GetFieldIDOrDie(env, configurationClass, "smallestScreenWidthDp", "I");
+  gConfigurationOffsets.mScreenWidthDpOffset =
+      GetFieldIDOrDie(env, configurationClass, "screenWidthDp", "I");
+  gConfigurationOffsets.mScreenHeightDpOffset =
+      GetFieldIDOrDie(env, configurationClass, "screenHeightDp", "I");
+
+  return RegisterMethodsOrDie(env, "android/content/res/AssetManager", gAssetManagerMethods,
+                              NELEM(gAssetManagerMethods));
 }
 
 }; // namespace android
diff --git a/core/jni/include/android_runtime/android_util_AssetManager.h b/core/jni/include/android_runtime/android_util_AssetManager.h
index 8dd9337..2c1e357 100644
--- a/core/jni/include/android_runtime/android_util_AssetManager.h
+++ b/core/jni/include/android_runtime/android_util_AssetManager.h
@@ -14,17 +14,20 @@
  * limitations under the License.
  */
 
-#ifndef android_util_AssetManager_H
-#define android_util_AssetManager_H
+#ifndef ANDROID_RUNTIME_ASSETMANAGER_H
+#define ANDROID_RUNTIME_ASSETMANAGER_H
 
-#include <androidfw/AssetManager.h>
+#include "androidfw/AssetManager2.h"
+#include "androidfw/MutexGuard.h"
 
 #include "jni.h"
 
 namespace android {
 
-extern AssetManager* assetManagerForJavaObject(JNIEnv* env, jobject assetMgr);
+extern AAssetManager* NdkAssetManagerForJavaObject(JNIEnv* env, jobject jassetmanager);
+extern Guarded<AssetManager2>* AssetManagerForJavaObject(JNIEnv* env, jobject jassetmanager);
+extern Guarded<AssetManager2>* AssetManagerForNdkAssetManager(AAssetManager* assetmanager);
 
-}
+}  // namespace android
 
-#endif
+#endif  // ANDROID_RUNTIME_ASSETMANAGER_H
diff --git a/core/proto/android/server/statlogger.proto b/core/proto/android/server/statlogger.proto
index 2ae526a..2b7daea 100644
--- a/core/proto/android/server/statlogger.proto
+++ b/core/proto/android/server/statlogger.proto
@@ -24,10 +24,13 @@
 
 // Dump from StatLogger.
 message StatLoggerProto {
-  option (.android.msg_privacy).dest = DEST_EXPLICIT;
+  option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
   message Event {
+    option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
     optional int32 eventId = 1;
+    // Labels are hard-coded in Android framework code.
     optional string label = 2;
     optional int32 count = 3;
     optional int64 total_duration_micros = 4;
diff --git a/core/res/res/drawable-watch/global_action_icon_background.xml b/core/res/res/drawable-watch/global_action_icon_background.xml
new file mode 100644
index 0000000..b7bc7e6
--- /dev/null
+++ b/core/res/res/drawable-watch/global_action_icon_background.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+        android:shape="oval"
+        android:tint="?android:attr/colorButtonNormal">
+    <solid android:color="@android:color/white"/>
+    <size android:height="40dp" android:width="40dp"/>
+</shape>
diff --git a/core/res/res/drawable/ic_qs_battery_saver.xml b/core/res/res/drawable/ic_qs_battery_saver.xml
new file mode 100644
index 0000000..89b2569
--- /dev/null
+++ b/core/res/res/drawable/ic_qs_battery_saver.xml
@@ -0,0 +1,28 @@
+<!--
+    Copyright (C) 2018 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:autoMirrored="true"
+        android:width="32.0dp"
+        android:height="32.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0"
+        android:tint="?android:attr/colorControlNormal">
+    <path
+            android:pathData="M5,3
+            l3.5,0 l0,-1.5 l7,0 l0,1.5 l3.5,0 l0,19.5 l-14,0z
+            M10.5,8.5 l0,3 l-3,0 l0,3 l3,0 l0,3 l3,0 l0,-3 l3,0 l0,-3 l-3,0 l0,-3 z"
+            android:fillColor="#FFFFFF"/>
+</vector>
diff --git a/core/res/res/layout-watch/global_actions_item.xml b/core/res/res/layout-watch/global_actions_item.xml
new file mode 100644
index 0000000..025d45e
--- /dev/null
+++ b/core/res/res/layout-watch/global_actions_item.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:minHeight="?attr/listPreferredItemHeightSmall"
+        android:gravity="center_vertical"
+        android:paddingStart="?attr/listPreferredItemPaddingStart"
+        android:paddingEnd="?attr/listPreferredItemPaddingEnd"
+        android:background="?attr/activatedBackgroundIndicator"
+        android:clipToPadding="false">
+    <ImageView android:id="@+id/icon"
+            android:background="@drawable/global_action_icon_background"
+            android:scaleType="centerInside"
+            android:layout_width="40dp"
+            android:layout_height="40dp"
+            android:padding="8dp"
+            android:gravity="center"
+            android:orientation="horizontal"
+            android:layout_marginEnd="8dp"
+            android:layout_marginTop="8dp"
+            android:layout_marginBottom="8dp"/>
+
+    <RelativeLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:layout_marginTop="8dp"
+            android:layout_marginBottom="8dp">
+
+        <TextView android:id="@+id/message"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="?attr/textAppearanceListItem"
+                android:ellipsize="end" />
+
+        <TextView android:id="@+id/status"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/message"
+                android:layout_alignStart="@id/message"
+                android:textAppearance="?attr/textAppearanceListItemSecondary"
+                android:textColor="?attr/textColorSecondary"/>
+    </RelativeLayout>
+</LinearLayout>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f38dcea..d59ba18 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -539,6 +539,15 @@
     <!-- status message in phone options dialog for when airplane mode is off -->
     <string name="global_actions_airplane_mode_off_status">Airplane mode is OFF</string>
 
+    <!-- label for item that enables battery saver in phone options dialog -->
+    <string name="global_action_toggle_battery_saver">Battery saver</string>
+
+    <!-- status message in phone options dialog for when battery saver is enabled -->
+    <string name="global_action_battery_saver_on_status">Battery saver is OFF</string>
+
+    <!-- status message in phone options dialog for when battery saver is disabled -->
+    <string name="global_action_battery_saver_off_status">Battery saver is ON</string>
+
     <!-- label for item that launches settings in phone options dialog [CHAR LIMIT=15]-->
     <string name="global_action_settings">Settings</string>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 8d67957..0cd1007 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1378,6 +1378,7 @@
   <java-symbol type="drawable" name="ic_corp_statusbar_icon" />
   <java-symbol type="drawable" name="ic_instant_icon_badge_bolt" />
   <java-symbol type="drawable" name="emulator_circular_window_overlay" />
+  <java-symbol type="drawable" name="ic_qs_battery_saver" />
 
   <java-symbol type="drawable" name="sim_light_blue" />
   <java-symbol type="drawable" name="sim_light_green" />
@@ -1738,6 +1739,9 @@
   <java-symbol type="string" name="global_action_silent_mode_off_status" />
   <java-symbol type="string" name="global_action_silent_mode_on_status" />
   <java-symbol type="string" name="global_action_toggle_silent_mode" />
+  <java-symbol type="string" name="global_action_battery_saver_off_status" />
+  <java-symbol type="string" name="global_action_battery_saver_on_status" />
+  <java-symbol type="string" name="global_action_toggle_battery_saver" />
   <java-symbol type="string" name="global_action_lockdown" />
   <java-symbol type="string" name="global_action_voice_assist" />
   <java-symbol type="string" name="global_action_assist" />
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index d6580d6..6c72ac1 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -231,6 +231,7 @@
                     Settings.Global.FORCE_ALLOW_ON_EXTERNAL,
                     Settings.Global.FORCED_APP_STANDBY_ENABLED,
                     Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED,
+                    Settings.Global.WIFI_ON_WHEN_PROXY_DISCONNECTED,
                     Settings.Global.FSTRIM_MANDATORY_INTERVAL,
                     Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
                     Settings.Global.GLOBAL_HTTP_PROXY_HOST,
diff --git a/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java b/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java
index a15d337..f3e10e0 100644
--- a/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java
+++ b/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java
@@ -214,6 +214,20 @@
     }
 
     @Test
+    public void testShortcutAvailable_onLockScreenAndLockScreenPreferenceUnset() {
+        // When the user hasn't specified a lock screen preference, we allow from the lock screen
+        // as long as the user has agreed to enable the shortcut
+        configureValidShortcutService();
+        configureShortcutEnabled(ENABLED_INCLUDING_LOCK_SCREEN);
+        Settings.Secure.putString(
+                mContentResolver, ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN, null);
+        Settings.Secure.putInt(mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 0);
+        assertFalse(getController().isAccessibilityShortcutAvailable(true));
+        Settings.Secure.putInt(mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 1);
+        assertTrue(getController().isAccessibilityShortcutAvailable(true));
+    }
+
+    @Test
     public void testShortcutAvailable_whenServiceIdBecomesNull_shouldReturnFalse() {
         configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
         configureValidShortcutService();
diff --git a/core/tests/coretests/src/com/android/internal/textservice/LazyIntToIntMapTest.java b/core/tests/coretests/src/com/android/internal/textservice/LazyIntToIntMapTest.java
new file mode 100644
index 0000000..3518527
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/textservice/LazyIntToIntMapTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.textservice;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.IntUnaryOperator;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class LazyIntToIntMapTest {
+    @Test
+    public void testLaziness() {
+        final IntUnaryOperator func = mock(IntUnaryOperator.class);
+        when(func.applyAsInt(eq(1))).thenReturn(11);
+        when(func.applyAsInt(eq(2))).thenReturn(22);
+
+        final LazyIntToIntMap map = new LazyIntToIntMap(func);
+
+        verify(func, never()).applyAsInt(anyInt());
+
+        assertEquals(22, map.get(2));
+        verify(func, times(0)).applyAsInt(eq(1));
+        verify(func, times(1)).applyAsInt(eq(2));
+
+        // Accessing to the same key does not evaluate the function again.
+        assertEquals(22, map.get(2));
+        verify(func, times(0)).applyAsInt(eq(1));
+        verify(func, times(1)).applyAsInt(eq(2));
+    }
+
+    @Test
+    public void testDelete() {
+        final IntUnaryOperator func1 = mock(IntUnaryOperator.class);
+        when(func1.applyAsInt(eq(1))).thenReturn(11);
+        when(func1.applyAsInt(eq(2))).thenReturn(22);
+
+        final IntUnaryOperator func2 = mock(IntUnaryOperator.class);
+        when(func2.applyAsInt(eq(1))).thenReturn(111);
+        when(func2.applyAsInt(eq(2))).thenReturn(222);
+
+        final AtomicReference<IntUnaryOperator> funcRef = new AtomicReference<>(func1);
+        final LazyIntToIntMap map = new LazyIntToIntMap(i -> funcRef.get().applyAsInt(i));
+
+        verify(func1, never()).applyAsInt(anyInt());
+        verify(func2, never()).applyAsInt(anyInt());
+
+        assertEquals(22, map.get(2));
+        verify(func1, times(1)).applyAsInt(eq(2));
+        verify(func2, times(0)).applyAsInt(eq(2));
+
+        // Swap func1 with func2 then invalidate the key=2
+        funcRef.set(func2);
+        map.delete(2);
+
+        // Calling get(2) again should re-evaluate the value.
+        assertEquals(222, map.get(2));
+        verify(func1, times(1)).applyAsInt(eq(2));
+        verify(func2, times(1)).applyAsInt(eq(2));
+
+        // Trying to delete non-existing keys does nothing.
+        map.delete(1);
+    }
+}
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index 251b2e7..70d5216 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -145,6 +145,7 @@
         "tests/TypeWrappers_test.cpp",
         "tests/ZipUtils_test.cpp",
     ],
+    static_libs: ["libgmock"],
     target: {
         android: {
             srcs: [
@@ -171,6 +172,7 @@
 
         // Actual benchmarks.
         "tests/AssetManager2_bench.cpp",
+        "tests/AttributeResolution_bench.cpp",
         "tests/SparseEntry_bench.cpp",
         "tests/Theme_bench.cpp",
     ],
diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp
index da0205d..8f58f74 100644
--- a/libs/androidfw/ApkAssets.cpp
+++ b/libs/androidfw/ApkAssets.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define ATRACE_TAG ATRACE_TAG_RESOURCES
-
 #include "androidfw/ApkAssets.h"
 
 #include <algorithm>
@@ -27,7 +25,6 @@
 #include "android-base/utf8.h"
 #include "utils/Compat.h"
 #include "utils/FileMap.h"
-#include "utils/Trace.h"
 #include "ziparchive/zip_archive.h"
 
 #include "androidfw/Asset.h"
@@ -105,8 +102,6 @@
 std::unique_ptr<const ApkAssets> ApkAssets::LoadImpl(
     unique_fd fd, const std::string& path, std::unique_ptr<Asset> idmap_asset,
     std::unique_ptr<const LoadedIdmap> loaded_idmap, bool system, bool load_as_shared_library) {
-  ATRACE_CALL();
-
   ::ZipArchiveHandle unmanaged_handle;
   int32_t result;
   if (fd >= 0) {
@@ -163,7 +158,6 @@
 }
 
 std::unique_ptr<Asset> ApkAssets::Open(const std::string& path, Asset::AccessMode mode) const {
-  ATRACE_CALL();
   CHECK(zip_handle_ != nullptr);
 
   ::ZipString name(path.c_str());
@@ -231,12 +225,16 @@
   while ((result = ::Next(cookie, &entry, &name)) == 0) {
     StringPiece full_file_path(reinterpret_cast<const char*>(name.name), name.name_length);
     StringPiece leaf_file_path = full_file_path.substr(root_path_full.size());
-    auto iter = std::find(leaf_file_path.begin(), leaf_file_path.end(), '/');
-    if (iter != leaf_file_path.end()) {
-      dirs.insert(
-          leaf_file_path.substr(0, std::distance(leaf_file_path.begin(), iter)).to_string());
-    } else if (!leaf_file_path.empty()) {
-      f(leaf_file_path, kFileTypeRegular);
+
+    if (!leaf_file_path.empty()) {
+      auto iter = std::find(leaf_file_path.begin(), leaf_file_path.end(), '/');
+      if (iter != leaf_file_path.end()) {
+        std::string dir =
+            leaf_file_path.substr(0, std::distance(leaf_file_path.begin(), iter)).to_string();
+        dirs.insert(std::move(dir));
+      } else {
+        f(leaf_file_path, kFileTypeRegular);
+      }
     }
   }
   ::EndIteration(cookie);
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index 415d3e3..d9f1293 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -36,6 +36,31 @@
 
 namespace android {
 
+struct FindEntryResult {
+  // A pointer to the resource table entry for this resource.
+  // If the size of the entry is > sizeof(ResTable_entry), it can be cast to
+  // a ResTable_map_entry and processed as a bag/map.
+  const ResTable_entry* entry;
+
+  // The configuration for which the resulting entry was defined. This is already swapped to host
+  // endianness.
+  ResTable_config config;
+
+  // The bitmask of configuration axis with which the resource value varies.
+  uint32_t type_flags;
+
+  // The dynamic package ID map for the package from which this resource came from.
+  const DynamicRefTable* dynamic_ref_table;
+
+  // The string pool reference to the type's name. This uses a different string pool than
+  // the global string pool, but this is hidden from the caller.
+  StringPoolRef type_string_ref;
+
+  // The string pool reference to the entry's name. This uses a different string pool than
+  // the global string pool, but this is hidden from the caller.
+  StringPoolRef entry_string_ref;
+};
+
 AssetManager2::AssetManager2() {
   memset(&configuration_, 0, sizeof(configuration_));
 }
@@ -44,6 +69,7 @@
                                  bool invalidate_caches) {
   apk_assets_ = apk_assets;
   BuildDynamicRefTable();
+  RebuildFilterList();
   if (invalidate_caches) {
     InvalidateCaches(static_cast<uint32_t>(-1));
   }
@@ -74,12 +100,14 @@
       if (idx == 0xff) {
         package_ids_[package_id] = idx = static_cast<uint8_t>(package_groups_.size());
         package_groups_.push_back({});
-        package_groups_.back().dynamic_ref_table.mAssignedPackageId = package_id;
+        DynamicRefTable& ref_table = package_groups_.back().dynamic_ref_table;
+        ref_table.mAssignedPackageId = package_id;
+        ref_table.mAppAsLib = package->IsDynamic() && package->GetPackageId() == 0x7f;
       }
       PackageGroup* package_group = &package_groups_[idx];
 
       // Add the package and to the set of packages with the same ID.
-      package_group->packages_.push_back(package.get());
+      package_group->packages_.push_back(ConfiguredPackage{package.get(), {}});
       package_group->cookies_.push_back(static_cast<ApkAssetsCookie>(i));
 
       // Add the package name -> build time ID mappings.
@@ -94,7 +122,7 @@
   // Now assign the runtime IDs so that we have a build-time to runtime ID map.
   const auto package_groups_end = package_groups_.end();
   for (auto iter = package_groups_.begin(); iter != package_groups_end; ++iter) {
-    const std::string& package_name = iter->packages_[0]->GetPackageName();
+    const std::string& package_name = iter->packages_[0].loaded_package_->GetPackageName();
     for (auto iter2 = package_groups_.begin(); iter2 != package_groups_end; ++iter2) {
       iter2->dynamic_ref_table.addMapping(String16(package_name.c_str(), package_name.size()),
                                           iter->dynamic_ref_table.mAssignedPackageId);
@@ -105,20 +133,33 @@
 void AssetManager2::DumpToLog() const {
   base::ScopedLogSeverity _log(base::INFO);
 
+  LOG(INFO) << base::StringPrintf("AssetManager2(this=%p)", this);
+
   std::string list;
+  for (const auto& apk_assets : apk_assets_) {
+    base::StringAppendF(&list, "%s,", apk_assets->GetPath().c_str());
+  }
+  LOG(INFO) << "ApkAssets: " << list;
+
+  list = "";
   for (size_t i = 0; i < package_ids_.size(); i++) {
     if (package_ids_[i] != 0xff) {
-      base::StringAppendF(&list, "%02x -> %d, ", (int) i, package_ids_[i]);
+      base::StringAppendF(&list, "%02x -> %d, ", (int)i, package_ids_[i]);
     }
   }
   LOG(INFO) << "Package ID map: " << list;
 
   for (const auto& package_group: package_groups_) {
-      list = "";
-      for (const auto& package : package_group.packages_) {
-        base::StringAppendF(&list, "%s(%02x), ", package->GetPackageName().c_str(), package->GetPackageId());
-      }
-      LOG(INFO) << base::StringPrintf("PG (%02x): ", package_group.dynamic_ref_table.mAssignedPackageId) << list;
+    list = "";
+    for (const auto& package : package_group.packages_) {
+      const LoadedPackage* loaded_package = package.loaded_package_;
+      base::StringAppendF(&list, "%s(%02x%s), ", loaded_package->GetPackageName().c_str(),
+                          loaded_package->GetPackageId(),
+                          (loaded_package->IsDynamic() ? " dynamic" : ""));
+    }
+    LOG(INFO) << base::StringPrintf("PG (%02x): ",
+                                    package_group.dynamic_ref_table.mAssignedPackageId)
+              << list;
   }
 }
 
@@ -157,53 +198,55 @@
   configuration_ = configuration;
 
   if (diff) {
+    RebuildFilterList();
     InvalidateCaches(static_cast<uint32_t>(diff));
   }
 }
 
 std::set<ResTable_config> AssetManager2::GetResourceConfigurations(bool exclude_system,
-                                                                   bool exclude_mipmap) {
-  ATRACE_CALL();
+                                                                   bool exclude_mipmap) const {
+  ATRACE_NAME("AssetManager::GetResourceConfigurations");
   std::set<ResTable_config> configurations;
   for (const PackageGroup& package_group : package_groups_) {
-    for (const LoadedPackage* package : package_group.packages_) {
-      if (exclude_system && package->IsSystem()) {
+    for (const ConfiguredPackage& package : package_group.packages_) {
+      if (exclude_system && package.loaded_package_->IsSystem()) {
         continue;
       }
-      package->CollectConfigurations(exclude_mipmap, &configurations);
+      package.loaded_package_->CollectConfigurations(exclude_mipmap, &configurations);
     }
   }
   return configurations;
 }
 
 std::set<std::string> AssetManager2::GetResourceLocales(bool exclude_system,
-                                                        bool merge_equivalent_languages) {
-  ATRACE_CALL();
+                                                        bool merge_equivalent_languages) const {
+  ATRACE_NAME("AssetManager::GetResourceLocales");
   std::set<std::string> locales;
   for (const PackageGroup& package_group : package_groups_) {
-    for (const LoadedPackage* package : package_group.packages_) {
-      if (exclude_system && package->IsSystem()) {
+    for (const ConfiguredPackage& package : package_group.packages_) {
+      if (exclude_system && package.loaded_package_->IsSystem()) {
         continue;
       }
-      package->CollectLocales(merge_equivalent_languages, &locales);
+      package.loaded_package_->CollectLocales(merge_equivalent_languages, &locales);
     }
   }
   return locales;
 }
 
-std::unique_ptr<Asset> AssetManager2::Open(const std::string& filename, Asset::AccessMode mode) {
+std::unique_ptr<Asset> AssetManager2::Open(const std::string& filename,
+                                           Asset::AccessMode mode) const {
   const std::string new_path = "assets/" + filename;
   return OpenNonAsset(new_path, mode);
 }
 
 std::unique_ptr<Asset> AssetManager2::Open(const std::string& filename, ApkAssetsCookie cookie,
-                                           Asset::AccessMode mode) {
+                                           Asset::AccessMode mode) const {
   const std::string new_path = "assets/" + filename;
   return OpenNonAsset(new_path, cookie, mode);
 }
 
-std::unique_ptr<AssetDir> AssetManager2::OpenDir(const std::string& dirname) {
-  ATRACE_CALL();
+std::unique_ptr<AssetDir> AssetManager2::OpenDir(const std::string& dirname) const {
+  ATRACE_NAME("AssetManager::OpenDir");
 
   std::string full_path = "assets/" + dirname;
   std::unique_ptr<SortedVector<AssetDir::FileInfo>> files =
@@ -236,8 +279,7 @@
 // is inconsistent for split APKs.
 std::unique_ptr<Asset> AssetManager2::OpenNonAsset(const std::string& filename,
                                                    Asset::AccessMode mode,
-                                                   ApkAssetsCookie* out_cookie) {
-  ATRACE_CALL();
+                                                   ApkAssetsCookie* out_cookie) const {
   for (int32_t i = apk_assets_.size() - 1; i >= 0; i--) {
     std::unique_ptr<Asset> asset = apk_assets_[i]->Open(filename, mode);
     if (asset) {
@@ -255,8 +297,8 @@
 }
 
 std::unique_ptr<Asset> AssetManager2::OpenNonAsset(const std::string& filename,
-                                                   ApkAssetsCookie cookie, Asset::AccessMode mode) {
-  ATRACE_CALL();
+                                                   ApkAssetsCookie cookie,
+                                                   Asset::AccessMode mode) const {
   if (cookie < 0 || static_cast<size_t>(cookie) >= apk_assets_.size()) {
     return {};
   }
@@ -264,14 +306,13 @@
 }
 
 ApkAssetsCookie AssetManager2::FindEntry(uint32_t resid, uint16_t density_override,
-                                         bool stop_at_first_match, FindEntryResult* out_entry) {
-  ATRACE_CALL();
-
+                                         bool /*stop_at_first_match*/,
+                                         FindEntryResult* out_entry) const {
   // Might use this if density_override != 0.
   ResTable_config density_override_config;
 
   // Select our configuration or generate a density override configuration.
-  ResTable_config* desired_config = &configuration_;
+  const ResTable_config* desired_config = &configuration_;
   if (density_override != 0 && density_override != configuration_.density) {
     density_override_config = configuration_;
     density_override_config.density = density_override;
@@ -285,55 +326,135 @@
 
   const uint32_t package_id = get_package_id(resid);
   const uint8_t type_idx = get_type_id(resid) - 1;
-  const uint16_t entry_id = get_entry_id(resid);
+  const uint16_t entry_idx = get_entry_id(resid);
 
-  const uint8_t idx = package_ids_[package_id];
-  if (idx == 0xff) {
+  const uint8_t package_idx = package_ids_[package_id];
+  if (package_idx == 0xff) {
     LOG(ERROR) << base::StringPrintf("No package ID %02x found for ID 0x%08x.", package_id, resid);
     return kInvalidCookie;
   }
 
-  FindEntryResult best_entry;
-  ApkAssetsCookie best_cookie = kInvalidCookie;
-  uint32_t cumulated_flags = 0u;
-
-  const PackageGroup& package_group = package_groups_[idx];
+  const PackageGroup& package_group = package_groups_[package_idx];
   const size_t package_count = package_group.packages_.size();
-  FindEntryResult current_entry;
-  for (size_t i = 0; i < package_count; i++) {
-    const LoadedPackage* loaded_package = package_group.packages_[i];
-    if (!loaded_package->FindEntry(type_idx, entry_id, *desired_config, &current_entry)) {
+
+  ApkAssetsCookie best_cookie = kInvalidCookie;
+  const LoadedPackage* best_package = nullptr;
+  const ResTable_type* best_type = nullptr;
+  const ResTable_config* best_config = nullptr;
+  ResTable_config best_config_copy;
+  uint32_t best_offset = 0u;
+  uint32_t type_flags = 0u;
+
+  // If desired_config is the same as the set configuration, then we can use our filtered list
+  // and we don't need to match the configurations, since they already matched.
+  const bool use_fast_path = desired_config == &configuration_;
+
+  for (size_t pi = 0; pi < package_count; pi++) {
+    const ConfiguredPackage& loaded_package_impl = package_group.packages_[pi];
+    const LoadedPackage* loaded_package = loaded_package_impl.loaded_package_;
+    ApkAssetsCookie cookie = package_group.cookies_[pi];
+
+    // If the type IDs are offset in this package, we need to take that into account when searching
+    // for a type.
+    const TypeSpec* type_spec = loaded_package->GetTypeSpecByTypeIndex(type_idx);
+    if (UNLIKELY(type_spec == nullptr)) {
       continue;
     }
 
-    cumulated_flags |= current_entry.type_flags;
+    uint16_t local_entry_idx = entry_idx;
 
-    const ResTable_config* current_config = current_entry.config;
-    const ResTable_config* best_config = best_entry.config;
-    if (best_cookie == kInvalidCookie ||
-        current_config->isBetterThan(*best_config, desired_config) ||
-        (loaded_package->IsOverlay() && current_config->compare(*best_config) == 0)) {
-      best_entry = current_entry;
-      best_cookie = package_group.cookies_[i];
-      if (stop_at_first_match) {
-        break;
+    // If there is an IDMAP supplied with this package, translate the entry ID.
+    if (type_spec->idmap_entries != nullptr) {
+      if (!LoadedIdmap::Lookup(type_spec->idmap_entries, local_entry_idx, &local_entry_idx)) {
+        // There is no mapping, so the resource is not meant to be in this overlay package.
+        continue;
+      }
+    }
+
+    type_flags |= type_spec->GetFlagsForEntryIndex(local_entry_idx);
+
+    // If the package is an overlay, then even configurations that are the same MUST be chosen.
+    const bool package_is_overlay = loaded_package->IsOverlay();
+
+    const FilteredConfigGroup& filtered_group = loaded_package_impl.filtered_configs_[type_idx];
+    if (use_fast_path) {
+      const std::vector<ResTable_config>& candidate_configs = filtered_group.configurations;
+      const size_t type_count = candidate_configs.size();
+      for (uint32_t i = 0; i < type_count; i++) {
+        const ResTable_config& this_config = candidate_configs[i];
+
+        // We can skip calling ResTable_config::match() because we know that all candidate
+        // configurations that do NOT match have been filtered-out.
+        if ((best_config == nullptr || this_config.isBetterThan(*best_config, desired_config)) ||
+            (package_is_overlay && this_config.compare(*best_config) == 0)) {
+          // The configuration matches and is better than the previous selection.
+          // Find the entry value if it exists for this configuration.
+          const ResTable_type* type_chunk = filtered_group.types[i];
+          const uint32_t offset = LoadedPackage::GetEntryOffset(type_chunk, local_entry_idx);
+          if (offset == ResTable_type::NO_ENTRY) {
+            continue;
+          }
+
+          best_cookie = cookie;
+          best_package = loaded_package;
+          best_type = type_chunk;
+          best_config = &this_config;
+          best_offset = offset;
+        }
+      }
+    } else {
+      // This is the slower path, which doesn't use the filtered list of configurations.
+      // Here we must read the ResTable_config from the mmapped APK, convert it to host endianness
+      // and fill in any new fields that did not exist when the APK was compiled.
+      // Furthermore when selecting configurations we can't just record the pointer to the
+      // ResTable_config, we must copy it.
+      const auto iter_end = type_spec->types + type_spec->type_count;
+      for (auto iter = type_spec->types; iter != iter_end; ++iter) {
+        ResTable_config this_config;
+        this_config.copyFromDtoH((*iter)->config);
+
+        if (this_config.match(*desired_config)) {
+          if ((best_config == nullptr || this_config.isBetterThan(*best_config, desired_config)) ||
+              (package_is_overlay && this_config.compare(*best_config) == 0)) {
+            // The configuration matches and is better than the previous selection.
+            // Find the entry value if it exists for this configuration.
+            const uint32_t offset = LoadedPackage::GetEntryOffset(*iter, local_entry_idx);
+            if (offset == ResTable_type::NO_ENTRY) {
+              continue;
+            }
+
+            best_cookie = cookie;
+            best_package = loaded_package;
+            best_type = *iter;
+            best_config_copy = this_config;
+            best_config = &best_config_copy;
+            best_offset = offset;
+          }
+        }
       }
     }
   }
 
-  if (best_cookie == kInvalidCookie) {
+  if (UNLIKELY(best_cookie == kInvalidCookie)) {
     return kInvalidCookie;
   }
 
-  *out_entry = best_entry;
+  const ResTable_entry* best_entry = LoadedPackage::GetEntryFromOffset(best_type, best_offset);
+  if (UNLIKELY(best_entry == nullptr)) {
+    return kInvalidCookie;
+  }
+
+  out_entry->entry = best_entry;
+  out_entry->config = *best_config;
+  out_entry->type_flags = type_flags;
+  out_entry->type_string_ref = StringPoolRef(best_package->GetTypeStringPool(), best_type->id - 1);
+  out_entry->entry_string_ref =
+      StringPoolRef(best_package->GetKeyStringPool(), best_entry->key.index);
   out_entry->dynamic_ref_table = &package_group.dynamic_ref_table;
-  out_entry->type_flags = cumulated_flags;
   return best_cookie;
 }
 
-bool AssetManager2::GetResourceName(uint32_t resid, ResourceName* out_name) {
-  ATRACE_CALL();
-
+bool AssetManager2::GetResourceName(uint32_t resid, ResourceName* out_name) const {
   FindEntryResult entry;
   ApkAssetsCookie cookie =
       FindEntry(resid, 0u /* density_override */, true /* stop_at_first_match */, &entry);
@@ -341,7 +462,8 @@
     return false;
   }
 
-  const LoadedPackage* package = apk_assets_[cookie]->GetLoadedArsc()->GetPackageForId(resid);
+  const LoadedPackage* package =
+      apk_assets_[cookie]->GetLoadedArsc()->GetPackageById(get_package_id(resid));
   if (package == nullptr) {
     return false;
   }
@@ -369,7 +491,7 @@
   return true;
 }
 
-bool AssetManager2::GetResourceFlags(uint32_t resid, uint32_t* out_flags) {
+bool AssetManager2::GetResourceFlags(uint32_t resid, uint32_t* out_flags) const {
   FindEntryResult entry;
   ApkAssetsCookie cookie =
       FindEntry(resid, 0u /* density_override */, false /* stop_at_first_match */, &entry);
@@ -383,9 +505,7 @@
 ApkAssetsCookie AssetManager2::GetResource(uint32_t resid, bool may_be_bag,
                                            uint16_t density_override, Res_value* out_value,
                                            ResTable_config* out_selected_config,
-                                           uint32_t* out_flags) {
-  ATRACE_CALL();
-
+                                           uint32_t* out_flags) const {
   FindEntryResult entry;
   ApkAssetsCookie cookie =
       FindEntry(resid, density_override, false /* stop_at_first_match */, &entry);
@@ -402,7 +522,7 @@
     // Create a reference since we can't represent this complex type as a Res_value.
     out_value->dataType = Res_value::TYPE_REFERENCE;
     out_value->data = resid;
-    *out_selected_config = *entry.config;
+    *out_selected_config = entry.config;
     *out_flags = entry.type_flags;
     return cookie;
   }
@@ -414,7 +534,7 @@
   // Convert the package ID to the runtime assigned package ID.
   entry.dynamic_ref_table->lookupResourceValue(out_value);
 
-  *out_selected_config = *entry.config;
+  *out_selected_config = entry.config;
   *out_flags = entry.type_flags;
   return cookie;
 }
@@ -422,16 +542,13 @@
 ApkAssetsCookie AssetManager2::ResolveReference(ApkAssetsCookie cookie, Res_value* in_out_value,
                                                 ResTable_config* in_out_selected_config,
                                                 uint32_t* in_out_flags,
-                                                uint32_t* out_last_reference) {
-  ATRACE_CALL();
+                                                uint32_t* out_last_reference) const {
   constexpr const int kMaxIterations = 20;
 
   for (size_t iteration = 0u; in_out_value->dataType == Res_value::TYPE_REFERENCE &&
                               in_out_value->data != 0u && iteration < kMaxIterations;
        iteration++) {
-    if (out_last_reference != nullptr) {
-      *out_last_reference = in_out_value->data;
-    }
+    *out_last_reference = in_out_value->data;
     uint32_t new_flags = 0u;
     cookie = GetResource(in_out_value->data, true /*may_be_bag*/, 0u /*density_override*/,
                          in_out_value, in_out_selected_config, &new_flags);
@@ -450,7 +567,7 @@
 }
 
 const ResolvedBag* AssetManager2::GetBag(uint32_t resid) {
-  ATRACE_CALL();
+  ATRACE_NAME("AssetManager::GetBag");
 
   auto cached_iter = cached_bags_.find(resid);
   if (cached_iter != cached_bags_.end()) {
@@ -492,7 +609,8 @@
         // Attributes, arrays, etc don't have a resource id as the name. They specify
         // other data, which would be wrong to change via a lookup.
         if (entry.dynamic_ref_table->lookupResourceId(&new_key) != NO_ERROR) {
-          LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", new_key, resid);
+          LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", new_key,
+                                           resid);
           return nullptr;
         }
       }
@@ -524,7 +642,8 @@
   const ResolvedBag* parent_bag = GetBag(parent_resid);
   if (parent_bag == nullptr) {
     // Failed to get the parent that should exist.
-    LOG(ERROR) << base::StringPrintf("Failed to find parent 0x%08x of bag 0x%08x.", parent_resid, resid);
+    LOG(ERROR) << base::StringPrintf("Failed to find parent 0x%08x of bag 0x%08x.", parent_resid,
+                                     resid);
     return nullptr;
   }
 
@@ -543,7 +662,8 @@
     uint32_t child_key = dtohl(map_entry->name.ident);
     if (!is_internal_resid(child_key)) {
       if (entry.dynamic_ref_table->lookupResourceId(&child_key) != NO_ERROR) {
-        LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", child_key, resid);
+        LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", child_key,
+                                         resid);
         return nullptr;
       }
     }
@@ -582,7 +702,8 @@
     uint32_t new_key = dtohl(map_entry->name.ident);
     if (!is_internal_resid(new_key)) {
       if (entry.dynamic_ref_table->lookupResourceId(&new_key) != NO_ERROR) {
-        LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", new_key, resid);
+        LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", new_key,
+                                         resid);
         return nullptr;
       }
     }
@@ -638,7 +759,7 @@
 
 uint32_t AssetManager2::GetResourceId(const std::string& resource_name,
                                       const std::string& fallback_type,
-                                      const std::string& fallback_package) {
+                                      const std::string& fallback_package) const {
   StringPiece package_name, type, entry;
   if (!ExtractResourceName(resource_name, &package_name, &type, &entry)) {
     return 0u;
@@ -670,7 +791,8 @@
   const static std::u16string kAttrPrivate16 = u"^attr-private";
 
   for (const PackageGroup& package_group : package_groups_) {
-    for (const LoadedPackage* package : package_group.packages_) {
+    for (const ConfiguredPackage& package_impl : package_group.packages_) {
+      const LoadedPackage* package = package_impl.loaded_package_;
       if (package_name != package->GetPackageName()) {
         // All packages in the same group are expected to have the same package name.
         break;
@@ -692,6 +814,32 @@
   return 0u;
 }
 
+void AssetManager2::RebuildFilterList() {
+  for (PackageGroup& group : package_groups_) {
+    for (ConfiguredPackage& impl : group.packages_) {
+      // Destroy it.
+      impl.filtered_configs_.~ByteBucketArray();
+
+      // Re-create it.
+      new (&impl.filtered_configs_) ByteBucketArray<FilteredConfigGroup>();
+
+      // Create the filters here.
+      impl.loaded_package_->ForEachTypeSpec([&](const TypeSpec* spec, uint8_t type_index) {
+        FilteredConfigGroup& group = impl.filtered_configs_.editItemAt(type_index);
+        const auto iter_end = spec->types + spec->type_count;
+        for (auto iter = spec->types; iter != iter_end; ++iter) {
+          ResTable_config this_config;
+          this_config.copyFromDtoH((*iter)->config);
+          if (this_config.match(configuration_)) {
+            group.configurations.push_back(this_config);
+            group.types.push_back(*iter);
+          }
+        }
+      });
+    }
+  }
+}
+
 void AssetManager2::InvalidateCaches(uint32_t diff) {
   if (diff == 0xffffffffu) {
     // Everything must go.
@@ -743,7 +891,7 @@
 };
 
 bool Theme::ApplyStyle(uint32_t resid, bool force) {
-  ATRACE_CALL();
+  ATRACE_NAME("Theme::ApplyStyle");
 
   const ResolvedBag* bag = asset_manager_->GetBag(resid);
   if (bag == nullptr) {
@@ -872,7 +1020,7 @@
 ApkAssetsCookie Theme::ResolveAttributeReference(ApkAssetsCookie cookie, Res_value* in_out_value,
                                                  ResTable_config* in_out_selected_config,
                                                  uint32_t* in_out_type_spec_flags,
-                                                 uint32_t* out_last_ref) {
+                                                 uint32_t* out_last_ref) const {
   if (in_out_value->dataType == Res_value::TYPE_ATTRIBUTE) {
     uint32_t new_flags;
     cookie = GetAttribute(in_out_value->data, in_out_value, &new_flags);
diff --git a/libs/androidfw/AttributeResolution.cpp b/libs/androidfw/AttributeResolution.cpp
index 60e3845..f912af4 100644
--- a/libs/androidfw/AttributeResolution.cpp
+++ b/libs/androidfw/AttributeResolution.cpp
@@ -20,13 +20,18 @@
 
 #include <log/log.h>
 
+#include "androidfw/AssetManager2.h"
 #include "androidfw/AttributeFinder.h"
-#include "androidfw/ResourceTypes.h"
 
 constexpr bool kDebugStyles = false;
 
 namespace android {
 
+// Java asset cookies have 0 as an invalid cookie, but TypedArray expects < 0.
+static uint32_t ApkAssetsCookieToJavaCookie(ApkAssetsCookie cookie) {
+  return cookie != kInvalidCookie ? static_cast<uint32_t>(cookie + 1) : static_cast<uint32_t>(-1);
+}
+
 class XmlAttributeFinder
     : public BackTrackingAttributeFinder<XmlAttributeFinder, size_t> {
  public:
@@ -44,58 +49,53 @@
 };
 
 class BagAttributeFinder
-    : public BackTrackingAttributeFinder<BagAttributeFinder, const ResTable::bag_entry*> {
+    : public BackTrackingAttributeFinder<BagAttributeFinder, const ResolvedBag::Entry*> {
  public:
-  BagAttributeFinder(const ResTable::bag_entry* start,
-                     const ResTable::bag_entry* end)
-      : BackTrackingAttributeFinder(start, end) {}
+  BagAttributeFinder(const ResolvedBag* bag)
+      : BackTrackingAttributeFinder(bag != nullptr ? bag->entries : nullptr,
+                                    bag != nullptr ? bag->entries + bag->entry_count : nullptr) {
+  }
 
-  inline uint32_t GetAttribute(const ResTable::bag_entry* entry) const {
-    return entry->map.name.ident;
+  inline uint32_t GetAttribute(const ResolvedBag::Entry* entry) const {
+    return entry->key;
   }
 };
 
-bool ResolveAttrs(ResTable::Theme* theme, uint32_t def_style_attr,
-                  uint32_t def_style_res, uint32_t* src_values,
-                  size_t src_values_length, uint32_t* attrs,
-                  size_t attrs_length, uint32_t* out_values,
-                  uint32_t* out_indices) {
+bool ResolveAttrs(Theme* theme, uint32_t def_style_attr, uint32_t def_style_res,
+                  uint32_t* src_values, size_t src_values_length, uint32_t* attrs,
+                  size_t attrs_length, uint32_t* out_values, uint32_t* out_indices) {
   if (kDebugStyles) {
     ALOGI("APPLY STYLE: theme=0x%p defStyleAttr=0x%x defStyleRes=0x%x", theme,
           def_style_attr, def_style_res);
   }
 
-  const ResTable& res = theme->getResTable();
+  AssetManager2* assetmanager = theme->GetAssetManager();
   ResTable_config config;
   Res_value value;
 
   int indices_idx = 0;
 
   // Load default style from attribute, if specified...
-  uint32_t def_style_bag_type_set_flags = 0;
+  uint32_t def_style_flags = 0u;
   if (def_style_attr != 0) {
     Res_value value;
-    if (theme->getAttribute(def_style_attr, &value, &def_style_bag_type_set_flags) >= 0) {
+    if (theme->GetAttribute(def_style_attr, &value, &def_style_flags) != kInvalidCookie) {
       if (value.dataType == Res_value::TYPE_REFERENCE) {
         def_style_res = value.data;
       }
     }
   }
 
-  // Now lock down the resource object and start pulling stuff from it.
-  res.lock();
-
   // Retrieve the default style bag, if requested.
-  const ResTable::bag_entry* def_style_start = nullptr;
-  uint32_t def_style_type_set_flags = 0;
-  ssize_t bag_off = def_style_res != 0
-                        ? res.getBagLocked(def_style_res, &def_style_start,
-                                           &def_style_type_set_flags)
-                        : -1;
-  def_style_type_set_flags |= def_style_bag_type_set_flags;
-  const ResTable::bag_entry* const def_style_end =
-      def_style_start + (bag_off >= 0 ? bag_off : 0);
-  BagAttributeFinder def_style_attr_finder(def_style_start, def_style_end);
+  const ResolvedBag* default_style_bag = nullptr;
+  if (def_style_res != 0) {
+    default_style_bag = assetmanager->GetBag(def_style_res);
+    if (default_style_bag != nullptr) {
+      def_style_flags |= default_style_bag->type_spec_flags;
+    }
+  }
+
+  BagAttributeFinder def_style_attr_finder(default_style_bag);
 
   // Now iterate through all of the attributes that the client has requested,
   // filling in each with whatever data we can find.
@@ -106,7 +106,7 @@
       ALOGI("RETRIEVING ATTR 0x%08x...", cur_ident);
     }
 
-    ssize_t block = -1;
+    ApkAssetsCookie cookie = kInvalidCookie;
     uint32_t type_set_flags = 0;
 
     value.dataType = Res_value::TYPE_NULL;
@@ -122,15 +122,14 @@
       value.dataType = Res_value::TYPE_ATTRIBUTE;
       value.data = src_values[ii];
       if (kDebugStyles) {
-        ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType,
-              value.data);
+        ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
       }
     } else {
-      const ResTable::bag_entry* const def_style_entry = def_style_attr_finder.Find(cur_ident);
-      if (def_style_entry != def_style_end) {
-        block = def_style_entry->stringBlock;
-        type_set_flags = def_style_type_set_flags;
-        value = def_style_entry->map.value;
+      const ResolvedBag::Entry* const entry = def_style_attr_finder.Find(cur_ident);
+      if (entry != def_style_attr_finder.end()) {
+        cookie = entry->cookie;
+        type_set_flags = def_style_flags;
+        value = entry->value;
         if (kDebugStyles) {
           ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
         }
@@ -140,22 +139,26 @@
     uint32_t resid = 0;
     if (value.dataType != Res_value::TYPE_NULL) {
       // Take care of resolving the found resource to its final value.
-      ssize_t new_block =
-          theme->resolveAttributeReference(&value, block, &resid, &type_set_flags, &config);
-      if (new_block >= 0) block = new_block;
+      ApkAssetsCookie new_cookie =
+          theme->ResolveAttributeReference(cookie, &value, &config, &type_set_flags, &resid);
+      if (new_cookie != kInvalidCookie) {
+        cookie = new_cookie;
+      }
       if (kDebugStyles) {
         ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
       }
     } else if (value.data != Res_value::DATA_NULL_EMPTY) {
-      // If we still don't have a value for this attribute, try to find
-      // it in the theme!
-      ssize_t new_block = theme->getAttribute(cur_ident, &value, &type_set_flags);
-      if (new_block >= 0) {
+      // If we still don't have a value for this attribute, try to find it in the theme!
+      ApkAssetsCookie new_cookie = theme->GetAttribute(cur_ident, &value, &type_set_flags);
+      if (new_cookie != kInvalidCookie) {
         if (kDebugStyles) {
           ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
         }
-        new_block = res.resolveReference(&value, new_block, &resid, &type_set_flags, &config);
-        if (new_block >= 0) block = new_block;
+        new_cookie =
+            assetmanager->ResolveReference(new_cookie, &value, &config, &type_set_flags, &resid);
+        if (new_cookie != kInvalidCookie) {
+          cookie = new_cookie;
+        }
         if (kDebugStyles) {
           ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
         }
@@ -169,7 +172,7 @@
       }
       value.dataType = Res_value::TYPE_NULL;
       value.data = Res_value::DATA_NULL_UNDEFINED;
-      block = -1;
+      cookie = kInvalidCookie;
     }
 
     if (kDebugStyles) {
@@ -179,9 +182,7 @@
     // Write the final value back to Java.
     out_values[STYLE_TYPE] = value.dataType;
     out_values[STYLE_DATA] = value.data;
-    out_values[STYLE_ASSET_COOKIE] =
-        block != -1 ? static_cast<uint32_t>(res.getTableCookie(block))
-                    : static_cast<uint32_t>(-1);
+    out_values[STYLE_ASSET_COOKIE] = ApkAssetsCookieToJavaCookie(cookie);
     out_values[STYLE_RESOURCE_ID] = resid;
     out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
     out_values[STYLE_DENSITY] = config.density;
@@ -195,90 +196,80 @@
     out_values += STYLE_NUM_ENTRIES;
   }
 
-  res.unlock();
-
   if (out_indices != nullptr) {
     out_indices[0] = indices_idx;
   }
   return true;
 }
 
-void ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr,
-                uint32_t def_style_res, const uint32_t* attrs, size_t attrs_length,
+void ApplyStyle(Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr,
+                uint32_t def_style_resid, const uint32_t* attrs, size_t attrs_length,
                 uint32_t* out_values, uint32_t* out_indices) {
   if (kDebugStyles) {
-    ALOGI("APPLY STYLE: theme=0x%p defStyleAttr=0x%x defStyleRes=0x%x xml=0x%p",
-          theme, def_style_attr, def_style_res, xml_parser);
+    ALOGI("APPLY STYLE: theme=0x%p defStyleAttr=0x%x defStyleRes=0x%x xml=0x%p", theme,
+          def_style_attr, def_style_resid, xml_parser);
   }
 
-  const ResTable& res = theme->getResTable();
+  AssetManager2* assetmanager = theme->GetAssetManager();
   ResTable_config config;
   Res_value value;
 
   int indices_idx = 0;
 
   // Load default style from attribute, if specified...
-  uint32_t def_style_bag_type_set_flags = 0;
+  uint32_t def_style_flags = 0u;
   if (def_style_attr != 0) {
     Res_value value;
-    if (theme->getAttribute(def_style_attr, &value,
-                            &def_style_bag_type_set_flags) >= 0) {
+    if (theme->GetAttribute(def_style_attr, &value, &def_style_flags) != kInvalidCookie) {
       if (value.dataType == Res_value::TYPE_REFERENCE) {
-        def_style_res = value.data;
+        def_style_resid = value.data;
       }
     }
   }
 
-  // Retrieve the style class associated with the current XML tag.
-  int style = 0;
-  uint32_t style_bag_type_set_flags = 0;
+  // Retrieve the style resource ID associated with the current XML tag's style attribute.
+  uint32_t style_resid = 0u;
+  uint32_t style_flags = 0u;
   if (xml_parser != nullptr) {
     ssize_t idx = xml_parser->indexOfStyle();
     if (idx >= 0 && xml_parser->getAttributeValue(idx, &value) >= 0) {
       if (value.dataType == value.TYPE_ATTRIBUTE) {
-        if (theme->getAttribute(value.data, &value, &style_bag_type_set_flags) < 0) {
+        // Resolve the attribute with out theme.
+        if (theme->GetAttribute(value.data, &value, &style_flags) == kInvalidCookie) {
           value.dataType = Res_value::TYPE_NULL;
         }
       }
+
       if (value.dataType == value.TYPE_REFERENCE) {
-        style = value.data;
+        style_resid = value.data;
       }
     }
   }
 
-  // Now lock down the resource object and start pulling stuff from it.
-  res.lock();
-
   // Retrieve the default style bag, if requested.
-  const ResTable::bag_entry* def_style_attr_start = nullptr;
-  uint32_t def_style_type_set_flags = 0;
-  ssize_t bag_off = def_style_res != 0
-                        ? res.getBagLocked(def_style_res, &def_style_attr_start,
-                                           &def_style_type_set_flags)
-                        : -1;
-  def_style_type_set_flags |= def_style_bag_type_set_flags;
-  const ResTable::bag_entry* const def_style_attr_end =
-      def_style_attr_start + (bag_off >= 0 ? bag_off : 0);
-  BagAttributeFinder def_style_attr_finder(def_style_attr_start,
-                                           def_style_attr_end);
+  const ResolvedBag* default_style_bag = nullptr;
+  if (def_style_resid != 0) {
+    default_style_bag = assetmanager->GetBag(def_style_resid);
+    if (default_style_bag != nullptr) {
+      def_style_flags |= default_style_bag->type_spec_flags;
+    }
+  }
+
+  BagAttributeFinder def_style_attr_finder(default_style_bag);
 
   // Retrieve the style class bag, if requested.
-  const ResTable::bag_entry* style_attr_start = nullptr;
-  uint32_t style_type_set_flags = 0;
-  bag_off =
-      style != 0
-          ? res.getBagLocked(style, &style_attr_start, &style_type_set_flags)
-          : -1;
-  style_type_set_flags |= style_bag_type_set_flags;
-  const ResTable::bag_entry* const style_attr_end =
-      style_attr_start + (bag_off >= 0 ? bag_off : 0);
-  BagAttributeFinder style_attr_finder(style_attr_start, style_attr_end);
+  const ResolvedBag* xml_style_bag = nullptr;
+  if (style_resid != 0) {
+    xml_style_bag = assetmanager->GetBag(style_resid);
+    if (xml_style_bag != nullptr) {
+      style_flags |= xml_style_bag->type_spec_flags;
+    }
+  }
+
+  BagAttributeFinder xml_style_attr_finder(xml_style_bag);
 
   // Retrieve the XML attributes, if requested.
-  static const ssize_t kXmlBlock = 0x10000000;
   XmlAttributeFinder xml_attr_finder(xml_parser);
-  const size_t xml_attr_end =
-      xml_parser != nullptr ? xml_parser->getAttributeCount() : 0;
 
   // Now iterate through all of the attributes that the client has requested,
   // filling in each with whatever data we can find.
@@ -289,8 +280,8 @@
       ALOGI("RETRIEVING ATTR 0x%08x...", cur_ident);
     }
 
-    ssize_t block = kXmlBlock;
-    uint32_t type_set_flags = 0;
+    ApkAssetsCookie cookie = kInvalidCookie;
+    uint32_t type_set_flags = 0u;
 
     value.dataType = Res_value::TYPE_NULL;
     value.data = Res_value::DATA_NULL_UNDEFINED;
@@ -302,7 +293,7 @@
 
     // Walk through the xml attributes looking for the requested attribute.
     const size_t xml_attr_idx = xml_attr_finder.Find(cur_ident);
-    if (xml_attr_idx != xml_attr_end) {
+    if (xml_attr_idx != xml_attr_finder.end()) {
       // We found the attribute we were looking for.
       xml_parser->getAttributeValue(xml_attr_idx, &value);
       if (kDebugStyles) {
@@ -312,12 +303,12 @@
 
     if (value.dataType == Res_value::TYPE_NULL && value.data != Res_value::DATA_NULL_EMPTY) {
       // Walk through the style class values looking for the requested attribute.
-      const ResTable::bag_entry* const style_attr_entry = style_attr_finder.Find(cur_ident);
-      if (style_attr_entry != style_attr_end) {
+      const ResolvedBag::Entry* entry = xml_style_attr_finder.Find(cur_ident);
+      if (entry != xml_style_attr_finder.end()) {
         // We found the attribute we were looking for.
-        block = style_attr_entry->stringBlock;
-        type_set_flags = style_type_set_flags;
-        value = style_attr_entry->map.value;
+        cookie = entry->cookie;
+        type_set_flags = style_flags;
+        value = entry->value;
         if (kDebugStyles) {
           ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data);
         }
@@ -326,25 +317,25 @@
 
     if (value.dataType == Res_value::TYPE_NULL && value.data != Res_value::DATA_NULL_EMPTY) {
       // Walk through the default style values looking for the requested attribute.
-      const ResTable::bag_entry* const def_style_attr_entry = def_style_attr_finder.Find(cur_ident);
-      if (def_style_attr_entry != def_style_attr_end) {
+      const ResolvedBag::Entry* entry = def_style_attr_finder.Find(cur_ident);
+      if (entry != def_style_attr_finder.end()) {
         // We found the attribute we were looking for.
-        block = def_style_attr_entry->stringBlock;
-        type_set_flags = style_type_set_flags;
-        value = def_style_attr_entry->map.value;
+        cookie = entry->cookie;
+        type_set_flags = def_style_flags;
+        value = entry->value;
         if (kDebugStyles) {
           ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
         }
       }
     }
 
-    uint32_t resid = 0;
+    uint32_t resid = 0u;
     if (value.dataType != Res_value::TYPE_NULL) {
       // Take care of resolving the found resource to its final value.
-      ssize_t new_block =
-          theme->resolveAttributeReference(&value, block, &resid, &type_set_flags, &config);
-      if (new_block >= 0) {
-        block = new_block;
+      ApkAssetsCookie new_cookie =
+          theme->ResolveAttributeReference(cookie, &value, &config, &type_set_flags, &resid);
+      if (new_cookie != kInvalidCookie) {
+        cookie = new_cookie;
       }
 
       if (kDebugStyles) {
@@ -352,14 +343,15 @@
       }
     } else if (value.data != Res_value::DATA_NULL_EMPTY) {
       // If we still don't have a value for this attribute, try to find it in the theme!
-      ssize_t new_block = theme->getAttribute(cur_ident, &value, &type_set_flags);
-      if (new_block >= 0) {
+      ApkAssetsCookie new_cookie = theme->GetAttribute(cur_ident, &value, &type_set_flags);
+      if (new_cookie != kInvalidCookie) {
         if (kDebugStyles) {
           ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
         }
-        new_block = res.resolveReference(&value, new_block, &resid, &type_set_flags, &config);
-        if (new_block >= 0) {
-          block = new_block;
+        new_cookie =
+            assetmanager->ResolveReference(new_cookie, &value, &config, &type_set_flags, &resid);
+        if (new_cookie != kInvalidCookie) {
+          cookie = new_cookie;
         }
 
         if (kDebugStyles) {
@@ -375,7 +367,7 @@
       }
       value.dataType = Res_value::TYPE_NULL;
       value.data = Res_value::DATA_NULL_UNDEFINED;
-      block = kXmlBlock;
+      cookie = kInvalidCookie;
     }
 
     if (kDebugStyles) {
@@ -385,9 +377,7 @@
     // Write the final value back to Java.
     out_values[STYLE_TYPE] = value.dataType;
     out_values[STYLE_DATA] = value.data;
-    out_values[STYLE_ASSET_COOKIE] =
-        block != kXmlBlock ? static_cast<uint32_t>(res.getTableCookie(block))
-                           : static_cast<uint32_t>(-1);
+    out_values[STYLE_ASSET_COOKIE] = ApkAssetsCookieToJavaCookie(cookie);
     out_values[STYLE_RESOURCE_ID] = resid;
     out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
     out_values[STYLE_DENSITY] = config.density;
@@ -402,36 +392,28 @@
     out_values += STYLE_NUM_ENTRIES;
   }
 
-  res.unlock();
-
   // out_indices must NOT be nullptr.
   out_indices[0] = indices_idx;
 }
 
-bool RetrieveAttributes(const ResTable* res, ResXMLParser* xml_parser,
-                        uint32_t* attrs, size_t attrs_length,
-                        uint32_t* out_values, uint32_t* out_indices) {
+bool RetrieveAttributes(AssetManager2* assetmanager, ResXMLParser* xml_parser, uint32_t* attrs,
+                        size_t attrs_length, uint32_t* out_values, uint32_t* out_indices) {
   ResTable_config config;
   Res_value value;
 
   int indices_idx = 0;
 
-  // Now lock down the resource object and start pulling stuff from it.
-  res->lock();
-
   // Retrieve the XML attributes, if requested.
   const size_t xml_attr_count = xml_parser->getAttributeCount();
   size_t ix = 0;
   uint32_t cur_xml_attr = xml_parser->getAttributeNameResID(ix);
 
-  static const ssize_t kXmlBlock = 0x10000000;
-
   // Now iterate through all of the attributes that the client has requested,
   // filling in each with whatever data we can find.
   for (size_t ii = 0; ii < attrs_length; ii++) {
     const uint32_t cur_ident = attrs[ii];
-    ssize_t block = kXmlBlock;
-    uint32_t type_set_flags = 0;
+    ApkAssetsCookie cookie = kInvalidCookie;
+    uint32_t type_set_flags = 0u;
 
     value.dataType = Res_value::TYPE_NULL;
     value.data = Res_value::DATA_NULL_UNDEFINED;
@@ -450,28 +432,27 @@
       cur_xml_attr = xml_parser->getAttributeNameResID(ix);
     }
 
-    uint32_t resid = 0;
+    uint32_t resid = 0u;
     if (value.dataType != Res_value::TYPE_NULL) {
       // Take care of resolving the found resource to its final value.
-      // printf("Resolving attribute reference\n");
-      ssize_t new_block = res->resolveReference(&value, block, &resid,
-                                                &type_set_flags, &config);
-      if (new_block >= 0) block = new_block;
+      ApkAssetsCookie new_cookie =
+          assetmanager->ResolveReference(cookie, &value, &config, &type_set_flags, &resid);
+      if (new_cookie != kInvalidCookie) {
+        cookie = new_cookie;
+      }
     }
 
     // Deal with the special @null value -- it turns back to TYPE_NULL.
     if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
       value.dataType = Res_value::TYPE_NULL;
       value.data = Res_value::DATA_NULL_UNDEFINED;
-      block = kXmlBlock;
+      cookie = kInvalidCookie;
     }
 
     // Write the final value back to Java.
     out_values[STYLE_TYPE] = value.dataType;
     out_values[STYLE_DATA] = value.data;
-    out_values[STYLE_ASSET_COOKIE] =
-        block != kXmlBlock ? static_cast<uint32_t>(res->getTableCookie(block))
-                           : static_cast<uint32_t>(-1);
+    out_values[STYLE_ASSET_COOKIE] = ApkAssetsCookieToJavaCookie(cookie);
     out_values[STYLE_RESOURCE_ID] = resid;
     out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
     out_values[STYLE_DENSITY] = config.density;
@@ -485,8 +466,6 @@
     out_values += STYLE_NUM_ENTRIES;
   }
 
-  res->unlock();
-
   if (out_indices != nullptr) {
     out_indices[0] = indices_idx;
   }
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index 28548e2..04d506a 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -44,44 +44,6 @@
 
 constexpr const static int kAppPackageId = 0x7f;
 
-// Element of a TypeSpec array. See TypeSpec.
-struct Type {
-  // The configuration for which this type defines entries.
-  // This is already converted to host endianness.
-  ResTable_config configuration;
-
-  // Pointer to the mmapped data where entry definitions are kept.
-  const ResTable_type* type;
-};
-
-// TypeSpec is going to be immediately proceeded by
-// an array of Type structs, all in the same block of memory.
-struct TypeSpec {
-  // Pointer to the mmapped data where flags are kept.
-  // Flags denote whether the resource entry is public
-  // and under which configurations it varies.
-  const ResTable_typeSpec* type_spec;
-
-  // Pointer to the mmapped data where the IDMAP mappings for this type
-  // exist. May be nullptr if no IDMAP exists.
-  const IdmapEntry_header* idmap_entries;
-
-  // The number of types that follow this struct.
-  // There is a type for each configuration
-  // that entries are defined for.
-  size_t type_count;
-
-  // Trick to easily access a variable number of Type structs
-  // proceeding this struct, and to ensure their alignment.
-  const Type types[0];
-};
-
-// TypeSpecPtr points to the block of memory that holds
-// a TypeSpec struct, followed by an array of Type structs.
-// TypeSpecPtr is a managed pointer that knows how to delete
-// itself.
-using TypeSpecPtr = util::unique_cptr<TypeSpec>;
-
 namespace {
 
 // Builder that helps accumulate Type structs and then create a single
@@ -95,21 +57,22 @@
   }
 
   void AddType(const ResTable_type* type) {
-    ResTable_config config;
-    config.copyFromDtoH(type->config);
-    types_.push_back(Type{config, type});
+    types_.push_back(type);
   }
 
   TypeSpecPtr Build() {
     // Check for overflow.
-    if ((std::numeric_limits<size_t>::max() - sizeof(TypeSpec)) / sizeof(Type) < types_.size()) {
+    using ElementType = const ResTable_type*;
+    if ((std::numeric_limits<size_t>::max() - sizeof(TypeSpec)) / sizeof(ElementType) <
+        types_.size()) {
       return {};
     }
-    TypeSpec* type_spec = (TypeSpec*)::malloc(sizeof(TypeSpec) + (types_.size() * sizeof(Type)));
+    TypeSpec* type_spec =
+        (TypeSpec*)::malloc(sizeof(TypeSpec) + (types_.size() * sizeof(ElementType)));
     type_spec->type_spec = header_;
     type_spec->idmap_entries = idmap_header_;
     type_spec->type_count = types_.size();
-    memcpy(type_spec + 1, types_.data(), types_.size() * sizeof(Type));
+    memcpy(type_spec + 1, types_.data(), types_.size() * sizeof(ElementType));
     return TypeSpecPtr(type_spec);
   }
 
@@ -118,7 +81,7 @@
 
   const ResTable_typeSpec* header_;
   const IdmapEntry_header* idmap_header_;
-  std::vector<Type> types_;
+  std::vector<const ResTable_type*> types_;
 };
 
 }  // namespace
@@ -162,18 +125,17 @@
   return true;
 }
 
-static bool VerifyResTableEntry(const ResTable_type* type, uint32_t entry_offset,
-                                size_t entry_idx) {
+static bool VerifyResTableEntry(const ResTable_type* type, uint32_t entry_offset) {
   // Check that the offset is aligned.
   if (entry_offset & 0x03) {
-    LOG(ERROR) << "Entry offset at index " << entry_idx << " is not 4-byte aligned.";
+    LOG(ERROR) << "Entry at offset " << entry_offset << " is not 4-byte aligned.";
     return false;
   }
 
   // Check that the offset doesn't overflow.
   if (entry_offset > std::numeric_limits<uint32_t>::max() - dtohl(type->entriesStart)) {
     // Overflow in offset.
-    LOG(ERROR) << "Entry offset at index " << entry_idx << " is too large.";
+    LOG(ERROR) << "Entry at offset " << entry_offset << " is too large.";
     return false;
   }
 
@@ -181,7 +143,7 @@
 
   entry_offset += dtohl(type->entriesStart);
   if (entry_offset > chunk_size - sizeof(ResTable_entry)) {
-    LOG(ERROR) << "Entry offset at index " << entry_idx
+    LOG(ERROR) << "Entry at offset " << entry_offset
                << " is too large. No room for ResTable_entry.";
     return false;
   }
@@ -191,13 +153,13 @@
 
   const size_t entry_size = dtohs(entry->size);
   if (entry_size < sizeof(*entry)) {
-    LOG(ERROR) << "ResTable_entry size " << entry_size << " at index " << entry_idx
+    LOG(ERROR) << "ResTable_entry size " << entry_size << " at offset " << entry_offset
                << " is too small.";
     return false;
   }
 
   if (entry_size > chunk_size || entry_offset > chunk_size - entry_size) {
-    LOG(ERROR) << "ResTable_entry size " << entry_size << " at index " << entry_idx
+    LOG(ERROR) << "ResTable_entry size " << entry_size << " at offset " << entry_offset
                << " is too large.";
     return false;
   }
@@ -205,7 +167,7 @@
   if (entry_size < sizeof(ResTable_map_entry)) {
     // There needs to be room for one Res_value struct.
     if (entry_offset + entry_size > chunk_size - sizeof(Res_value)) {
-      LOG(ERROR) << "No room for Res_value after ResTable_entry at index " << entry_idx
+      LOG(ERROR) << "No room for Res_value after ResTable_entry at offset " << entry_offset
                  << " for type " << (int)type->id << ".";
       return false;
     }
@@ -214,12 +176,12 @@
         reinterpret_cast<const Res_value*>(reinterpret_cast<const uint8_t*>(entry) + entry_size);
     const size_t value_size = dtohs(value->size);
     if (value_size < sizeof(Res_value)) {
-      LOG(ERROR) << "Res_value at index " << entry_idx << " is too small.";
+      LOG(ERROR) << "Res_value at offset " << entry_offset << " is too small.";
       return false;
     }
 
     if (value_size > chunk_size || entry_offset + entry_size > chunk_size - value_size) {
-      LOG(ERROR) << "Res_value size " << value_size << " at index " << entry_idx
+      LOG(ERROR) << "Res_value size " << value_size << " at offset " << entry_offset
                  << " is too large.";
       return false;
     }
@@ -228,119 +190,76 @@
     const size_t map_entry_count = dtohl(map->count);
     size_t map_entries_start = entry_offset + entry_size;
     if (map_entries_start & 0x03) {
-      LOG(ERROR) << "Map entries at index " << entry_idx << " start at unaligned offset.";
+      LOG(ERROR) << "Map entries at offset " << entry_offset << " start at unaligned offset.";
       return false;
     }
 
     // Each entry is sizeof(ResTable_map) big.
     if (map_entry_count > ((chunk_size - map_entries_start) / sizeof(ResTable_map))) {
-      LOG(ERROR) << "Too many map entries in ResTable_map_entry at index " << entry_idx << ".";
+      LOG(ERROR) << "Too many map entries in ResTable_map_entry at offset " << entry_offset << ".";
       return false;
     }
   }
   return true;
 }
 
-bool LoadedPackage::FindEntry(const TypeSpecPtr& type_spec_ptr, uint16_t entry_idx,
-                              const ResTable_config& config, FindEntryResult* out_entry) const {
-  const ResTable_config* best_config = nullptr;
-  const ResTable_type* best_type = nullptr;
-  uint32_t best_offset = 0;
+const ResTable_entry* LoadedPackage::GetEntry(const ResTable_type* type_chunk,
+                                              uint16_t entry_index) {
+  uint32_t entry_offset = GetEntryOffset(type_chunk, entry_index);
+  if (entry_offset == ResTable_type::NO_ENTRY) {
+    return nullptr;
+  }
+  return GetEntryFromOffset(type_chunk, entry_offset);
+}
 
-  for (uint32_t i = 0; i < type_spec_ptr->type_count; i++) {
-    const Type* type = &type_spec_ptr->types[i];
-    const ResTable_type* type_chunk = type->type;
+uint32_t LoadedPackage::GetEntryOffset(const ResTable_type* type_chunk, uint16_t entry_index) {
+  // The configuration matches and is better than the previous selection.
+  // Find the entry value if it exists for this configuration.
+  const size_t entry_count = dtohl(type_chunk->entryCount);
+  const size_t offsets_offset = dtohs(type_chunk->header.headerSize);
 
-    if (type->configuration.match(config) &&
-        (best_config == nullptr || type->configuration.isBetterThan(*best_config, &config))) {
-      // The configuration matches and is better than the previous selection.
-      // Find the entry value if it exists for this configuration.
-      const size_t entry_count = dtohl(type_chunk->entryCount);
-      const size_t offsets_offset = dtohs(type_chunk->header.headerSize);
+  // Check if there is the desired entry in this type.
 
-      // Check if there is the desired entry in this type.
-
-      if (type_chunk->flags & ResTable_type::FLAG_SPARSE) {
-        // This is encoded as a sparse map, so perform a binary search.
-        const ResTable_sparseTypeEntry* sparse_indices =
-            reinterpret_cast<const ResTable_sparseTypeEntry*>(
-                reinterpret_cast<const uint8_t*>(type_chunk) + offsets_offset);
-        const ResTable_sparseTypeEntry* sparse_indices_end = sparse_indices + entry_count;
-        const ResTable_sparseTypeEntry* result =
-            std::lower_bound(sparse_indices, sparse_indices_end, entry_idx,
-                             [](const ResTable_sparseTypeEntry& entry, uint16_t entry_idx) {
-                               return dtohs(entry.idx) < entry_idx;
-                             });
-
-        if (result == sparse_indices_end || dtohs(result->idx) != entry_idx) {
-          // No entry found.
-          continue;
-        }
-
-        // Extract the offset from the entry. Each offset must be a multiple of 4 so we store it as
-        // the real offset divided by 4.
-        best_offset = uint32_t{dtohs(result->offset)} * 4u;
-      } else {
-        if (entry_idx >= entry_count) {
-          // This entry cannot be here.
-          continue;
-        }
-
-        const uint32_t* entry_offsets = reinterpret_cast<const uint32_t*>(
+  if (type_chunk->flags & ResTable_type::FLAG_SPARSE) {
+    // This is encoded as a sparse map, so perform a binary search.
+    const ResTable_sparseTypeEntry* sparse_indices =
+        reinterpret_cast<const ResTable_sparseTypeEntry*>(
             reinterpret_cast<const uint8_t*>(type_chunk) + offsets_offset);
-        const uint32_t offset = dtohl(entry_offsets[entry_idx]);
-        if (offset == ResTable_type::NO_ENTRY) {
-          continue;
-        }
+    const ResTable_sparseTypeEntry* sparse_indices_end = sparse_indices + entry_count;
+    const ResTable_sparseTypeEntry* result =
+        std::lower_bound(sparse_indices, sparse_indices_end, entry_index,
+                         [](const ResTable_sparseTypeEntry& entry, uint16_t entry_idx) {
+                           return dtohs(entry.idx) < entry_idx;
+                         });
 
-        // There is an entry for this resource, record it.
-        best_offset = offset;
-      }
-
-      best_config = &type->configuration;
-      best_type = type_chunk;
+    if (result == sparse_indices_end || dtohs(result->idx) != entry_index) {
+      // No entry found.
+      return ResTable_type::NO_ENTRY;
     }
+
+    // Extract the offset from the entry. Each offset must be a multiple of 4 so we store it as
+    // the real offset divided by 4.
+    return uint32_t{dtohs(result->offset)} * 4u;
   }
 
-  if (best_type == nullptr) {
-    return false;
+  // This type is encoded as a dense array.
+  if (entry_index >= entry_count) {
+    // This entry cannot be here.
+    return ResTable_type::NO_ENTRY;
   }
 
-  if (UNLIKELY(!VerifyResTableEntry(best_type, best_offset, entry_idx))) {
-    return false;
-  }
-
-  const ResTable_entry* best_entry = reinterpret_cast<const ResTable_entry*>(
-      reinterpret_cast<const uint8_t*>(best_type) + best_offset + dtohl(best_type->entriesStart));
-
-  const uint32_t* flags = reinterpret_cast<const uint32_t*>(type_spec_ptr->type_spec + 1);
-  out_entry->type_flags = dtohl(flags[entry_idx]);
-  out_entry->entry = best_entry;
-  out_entry->config = best_config;
-  out_entry->type_string_ref = StringPoolRef(&type_string_pool_, best_type->id - 1);
-  out_entry->entry_string_ref = StringPoolRef(&key_string_pool_, dtohl(best_entry->key.index));
-  return true;
+  const uint32_t* entry_offsets = reinterpret_cast<const uint32_t*>(
+      reinterpret_cast<const uint8_t*>(type_chunk) + offsets_offset);
+  return dtohl(entry_offsets[entry_index]);
 }
 
-bool LoadedPackage::FindEntry(uint8_t type_idx, uint16_t entry_idx, const ResTable_config& config,
-                              FindEntryResult* out_entry) const {
-  ATRACE_CALL();
-
-  // If the type IDs are offset in this package, we need to take that into account when searching
-  // for a type.
-  const TypeSpecPtr& ptr = type_specs_[type_idx - type_id_offset_];
-  if (UNLIKELY(ptr == nullptr)) {
-    return false;
+const ResTable_entry* LoadedPackage::GetEntryFromOffset(const ResTable_type* type_chunk,
+                                                        uint32_t offset) {
+  if (UNLIKELY(!VerifyResTableEntry(type_chunk, offset))) {
+    return nullptr;
   }
-
-  // If there is an IDMAP supplied with this package, translate the entry ID.
-  if (ptr->idmap_entries != nullptr) {
-    if (!LoadedIdmap::Lookup(ptr->idmap_entries, entry_idx, &entry_idx)) {
-      // There is no mapping, so the resource is not meant to be in this overlay package.
-      return false;
-    }
-  }
-  return FindEntry(ptr, entry_idx, config, out_entry);
+  return reinterpret_cast<const ResTable_entry*>(reinterpret_cast<const uint8_t*>(type_chunk) +
+                                                 offset + dtohl(type_chunk->entriesStart));
 }
 
 void LoadedPackage::CollectConfigurations(bool exclude_mipmap,
@@ -348,7 +267,7 @@
   const static std::u16string kMipMap = u"mipmap";
   const size_t type_count = type_specs_.size();
   for (size_t i = 0; i < type_count; i++) {
-    const util::unique_cptr<TypeSpec>& type_spec = type_specs_[i];
+    const TypeSpecPtr& type_spec = type_specs_[i];
     if (type_spec != nullptr) {
       if (exclude_mipmap) {
         const int type_idx = type_spec->type_spec->id - 1;
@@ -369,8 +288,11 @@
         }
       }
 
-      for (size_t j = 0; j < type_spec->type_count; j++) {
-        out_configs->insert(type_spec->types[j].configuration);
+      const auto iter_end = type_spec->types + type_spec->type_count;
+      for (auto iter = type_spec->types; iter != iter_end; ++iter) {
+        ResTable_config config;
+        config.copyFromDtoH((*iter)->config);
+        out_configs->insert(config);
       }
     }
   }
@@ -380,10 +302,12 @@
   char temp_locale[RESTABLE_MAX_LOCALE_LEN];
   const size_t type_count = type_specs_.size();
   for (size_t i = 0; i < type_count; i++) {
-    const util::unique_cptr<TypeSpec>& type_spec = type_specs_[i];
+    const TypeSpecPtr& type_spec = type_specs_[i];
     if (type_spec != nullptr) {
-      for (size_t j = 0; j < type_spec->type_count; j++) {
-        const ResTable_config& configuration = type_spec->types[j].configuration;
+      const auto iter_end = type_spec->types + type_spec->type_count;
+      for (auto iter = type_spec->types; iter != iter_end; ++iter) {
+        ResTable_config configuration;
+        configuration.copyFromDtoH((*iter)->config);
         if (configuration.locale != 0) {
           configuration.getBcp47Locale(temp_locale, canonicalize);
           std::string locale(temp_locale);
@@ -411,17 +335,17 @@
     return 0u;
   }
 
-  for (size_t ti = 0; ti < type_spec->type_count; ti++) {
-    const Type* type = &type_spec->types[ti];
-    size_t entry_count = dtohl(type->type->entryCount);
+  const auto iter_end = type_spec->types + type_spec->type_count;
+  for (auto iter = type_spec->types; iter != iter_end; ++iter) {
+    const ResTable_type* type = *iter;
+    size_t entry_count = dtohl(type->entryCount);
     for (size_t entry_idx = 0; entry_idx < entry_count; entry_idx++) {
       const uint32_t* entry_offsets = reinterpret_cast<const uint32_t*>(
-          reinterpret_cast<const uint8_t*>(type->type) + dtohs(type->type->header.headerSize));
+          reinterpret_cast<const uint8_t*>(type) + dtohs(type->header.headerSize));
       const uint32_t offset = dtohl(entry_offsets[entry_idx]);
       if (offset != ResTable_type::NO_ENTRY) {
-        const ResTable_entry* entry =
-            reinterpret_cast<const ResTable_entry*>(reinterpret_cast<const uint8_t*>(type->type) +
-                                                    dtohl(type->type->entriesStart) + offset);
+        const ResTable_entry* entry = reinterpret_cast<const ResTable_entry*>(
+            reinterpret_cast<const uint8_t*>(type) + dtohl(type->entriesStart) + offset);
         if (dtohl(entry->key.index) == static_cast<uint32_t>(key_idx)) {
           // The package ID will be overridden by the caller (due to runtime assignment of package
           // IDs for shared libraries).
@@ -433,8 +357,7 @@
   return 0u;
 }
 
-const LoadedPackage* LoadedArsc::GetPackageForId(uint32_t resid) const {
-  const uint8_t package_id = get_package_id(resid);
+const LoadedPackage* LoadedArsc::GetPackageById(uint8_t package_id) const {
   for (const auto& loaded_package : packages_) {
     if (loaded_package->GetPackageId() == package_id) {
       return loaded_package.get();
@@ -446,7 +369,7 @@
 std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk,
                                                          const LoadedIdmap* loaded_idmap,
                                                          bool system, bool load_as_shared_library) {
-  ATRACE_CALL();
+  ATRACE_NAME("LoadedPackage::Load");
   std::unique_ptr<LoadedPackage> loaded_package(new LoadedPackage());
 
   // typeIdOffset was added at some point, but we still must recognize apps built before this
@@ -486,14 +409,10 @@
   util::ReadUtf16StringFromDevice(header->name, arraysize(header->name),
                                   &loaded_package->package_name_);
 
-  // A TypeSpec builder. We use this to accumulate the set of Types
-  // available for a TypeSpec, and later build a single, contiguous block
-  // of memory that holds all the Types together with the TypeSpec.
-  std::unique_ptr<TypeSpecPtrBuilder> types_builder;
-
-  // Keep track of the last seen type index. Since type IDs are 1-based,
-  // this records their index, which is 0-based (type ID - 1).
-  uint8_t last_type_idx = 0;
+  // A map of TypeSpec builders, each associated with an type index.
+  // We use these to accumulate the set of Types available for a TypeSpec, and later build a single,
+  // contiguous block of memory that holds all the Types together with the TypeSpec.
+  std::unordered_map<int, std::unique_ptr<TypeSpecPtrBuilder>> type_builder_map;
 
   ChunkIterator iter(chunk.data_ptr(), chunk.data_size());
   while (iter.HasNext()) {
@@ -525,30 +444,6 @@
       } break;
 
       case RES_TABLE_TYPE_SPEC_TYPE: {
-        ATRACE_NAME("LoadTableTypeSpec");
-
-        // Starting a new TypeSpec, so finish the old one if there was one.
-        if (types_builder) {
-          TypeSpecPtr type_spec_ptr = types_builder->Build();
-          if (type_spec_ptr == nullptr) {
-            LOG(ERROR) << "Too many type configurations, overflow detected.";
-            return {};
-          }
-
-          // We only add the type to the package if there is no IDMAP, or if the type is
-          // overlaying something.
-          if (loaded_idmap == nullptr || type_spec_ptr->idmap_entries != nullptr) {
-            // If this is an overlay, insert it at the target type ID.
-            if (type_spec_ptr->idmap_entries != nullptr) {
-              last_type_idx = dtohs(type_spec_ptr->idmap_entries->target_type_id) - 1;
-            }
-            loaded_package->type_specs_.editItemAt(last_type_idx) = std::move(type_spec_ptr);
-          }
-
-          types_builder = {};
-          last_type_idx = 0;
-        }
-
         const ResTable_typeSpec* type_spec = child_chunk.header<ResTable_typeSpec>();
         if (type_spec == nullptr) {
           LOG(ERROR) << "RES_TABLE_TYPE_SPEC_TYPE too small.";
@@ -583,8 +478,6 @@
           return {};
         }
 
-        last_type_idx = type_spec->id - 1;
-
         // If this is an overlay, associate the mapping of this type to the target type
         // from the IDMAP.
         const IdmapEntry_header* idmap_entry_header = nullptr;
@@ -592,7 +485,13 @@
           idmap_entry_header = loaded_idmap->GetEntryMapForType(type_spec->id);
         }
 
-        types_builder = util::make_unique<TypeSpecPtrBuilder>(type_spec, idmap_entry_header);
+        std::unique_ptr<TypeSpecPtrBuilder>& builder_ptr = type_builder_map[type_spec->id - 1];
+        if (builder_ptr == nullptr) {
+          builder_ptr = util::make_unique<TypeSpecPtrBuilder>(type_spec, idmap_entry_header);
+        } else {
+          LOG(WARNING) << StringPrintf("RES_TABLE_TYPE_SPEC_TYPE already defined for ID %02x",
+                                       type_spec->id);
+        }
       } break;
 
       case RES_TABLE_TYPE_TYPE: {
@@ -607,12 +506,15 @@
         }
 
         // Type chunks must be preceded by their TypeSpec chunks.
-        if (!types_builder || type->id - 1 != last_type_idx) {
-          LOG(ERROR) << "RES_TABLE_TYPE_TYPE found without preceding RES_TABLE_TYPE_SPEC_TYPE.";
+        std::unique_ptr<TypeSpecPtrBuilder>& builder_ptr = type_builder_map[type->id - 1];
+        if (builder_ptr != nullptr) {
+          builder_ptr->AddType(type);
+        } else {
+          LOG(ERROR) << StringPrintf(
+              "RES_TABLE_TYPE_TYPE with ID %02x found without preceding RES_TABLE_TYPE_SPEC_TYPE.",
+              type->id);
           return {};
         }
-
-        types_builder->AddType(type);
       } break;
 
       case RES_TABLE_LIBRARY_TYPE: {
@@ -638,7 +540,7 @@
                                           arraysize(entry_iter->packageName), &package_name);
 
           if (dtohl(entry_iter->packageId) >= std::numeric_limits<uint8_t>::max()) {
-            LOG(ERROR) << base::StringPrintf(
+            LOG(ERROR) << StringPrintf(
                 "Package ID %02x in RES_TABLE_LIBRARY_TYPE too large for package '%s'.",
                 dtohl(entry_iter->packageId), package_name.c_str());
             return {};
@@ -651,14 +553,20 @@
       } break;
 
       default:
-        LOG(WARNING) << base::StringPrintf("Unknown chunk type '%02x'.", chunk.type());
+        LOG(WARNING) << StringPrintf("Unknown chunk type '%02x'.", chunk.type());
         break;
     }
   }
 
-  // Finish the last TypeSpec.
-  if (types_builder) {
-    TypeSpecPtr type_spec_ptr = types_builder->Build();
+  if (iter.HadError()) {
+    LOG(ERROR) << iter.GetLastError();
+    return {};
+  }
+
+  // Flatten and construct the TypeSpecs.
+  for (auto& entry : type_builder_map) {
+    uint8_t type_idx = static_cast<uint8_t>(entry.first);
+    TypeSpecPtr type_spec_ptr = entry.second->Build();
     if (type_spec_ptr == nullptr) {
       LOG(ERROR) << "Too many type configurations, overflow detected.";
       return {};
@@ -669,43 +577,17 @@
     if (loaded_idmap == nullptr || type_spec_ptr->idmap_entries != nullptr) {
       // If this is an overlay, insert it at the target type ID.
       if (type_spec_ptr->idmap_entries != nullptr) {
-        last_type_idx = dtohs(type_spec_ptr->idmap_entries->target_type_id) - 1;
+        type_idx = dtohs(type_spec_ptr->idmap_entries->target_type_id) - 1;
       }
-      loaded_package->type_specs_.editItemAt(last_type_idx) = std::move(type_spec_ptr);
+      loaded_package->type_specs_.editItemAt(type_idx) = std::move(type_spec_ptr);
     }
   }
 
-  if (iter.HadError()) {
-    LOG(ERROR) << iter.GetLastError();
-    return {};
-  }
   return std::move(loaded_package);
 }
 
-bool LoadedArsc::FindEntry(uint32_t resid, const ResTable_config& config,
-                           FindEntryResult* out_entry) const {
-  ATRACE_CALL();
-
-  const uint8_t package_id = get_package_id(resid);
-  const uint8_t type_id = get_type_id(resid);
-  const uint16_t entry_id = get_entry_id(resid);
-
-  if (UNLIKELY(type_id == 0)) {
-    LOG(ERROR) << base::StringPrintf("Invalid ID 0x%08x.", resid);
-    return false;
-  }
-
-  for (const auto& loaded_package : packages_) {
-    if (loaded_package->GetPackageId() == package_id) {
-      return loaded_package->FindEntry(type_id - 1, entry_id, config, out_entry);
-    }
-  }
-  return false;
-}
-
 bool LoadedArsc::LoadTable(const Chunk& chunk, const LoadedIdmap* loaded_idmap,
                            bool load_as_shared_library) {
-  ATRACE_CALL();
   const ResTable_header* header = chunk.header<ResTable_header>();
   if (header == nullptr) {
     LOG(ERROR) << "RES_TABLE_TYPE too small.";
@@ -752,7 +634,7 @@
       } break;
 
       default:
-        LOG(WARNING) << base::StringPrintf("Unknown chunk type '%02x'.", chunk.type());
+        LOG(WARNING) << StringPrintf("Unknown chunk type '%02x'.", chunk.type());
         break;
     }
   }
@@ -767,7 +649,7 @@
 std::unique_ptr<const LoadedArsc> LoadedArsc::Load(const StringPiece& data,
                                                    const LoadedIdmap* loaded_idmap, bool system,
                                                    bool load_as_shared_library) {
-  ATRACE_CALL();
+  ATRACE_NAME("LoadedArsc::LoadTable");
 
   // Not using make_unique because the constructor is private.
   std::unique_ptr<LoadedArsc> loaded_arsc(new LoadedArsc());
@@ -784,7 +666,7 @@
         break;
 
       default:
-        LOG(WARNING) << base::StringPrintf("Unknown chunk type '%02x'.", chunk.type());
+        LOG(WARNING) << StringPrintf("Unknown chunk type '%02x'.", chunk.type());
         break;
     }
   }
diff --git a/libs/androidfw/OWNERS b/libs/androidfw/OWNERS
new file mode 100644
index 0000000..23ec5ab
--- /dev/null
+++ b/libs/androidfw/OWNERS
@@ -0,0 +1,2 @@
+set noparent
+toddke@google.com
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index b033137..ef08897 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -69,6 +69,8 @@
   Entry entries[0];
 };
 
+struct FindEntryResult;
+
 // AssetManager2 is the main entry point for accessing assets and resources.
 // AssetManager2 provides caching of resources retrieved via the underlying ApkAssets.
 class AssetManager2 {
@@ -127,7 +129,7 @@
   // If `exclude_mipmap` is set to true, resource configurations defined for resource type 'mipmap'
   // will be excluded from the list.
   std::set<ResTable_config> GetResourceConfigurations(bool exclude_system = false,
-                                                      bool exclude_mipmap = false);
+                                                      bool exclude_mipmap = false) const;
 
   // Returns all the locales for which there are resources defined. This includes resource
   // locales in all the ApkAssets set for this AssetManager.
@@ -136,24 +138,24 @@
   // If `merge_equivalent_languages` is set to true, resource locales will be canonicalized
   // and de-duped in the resulting list.
   std::set<std::string> GetResourceLocales(bool exclude_system = false,
-                                           bool merge_equivalent_languages = false);
+                                           bool merge_equivalent_languages = false) const;
 
   // Searches the set of APKs loaded by this AssetManager and opens the first one found located
   // in the assets/ directory.
   // `mode` controls how the file is opened.
   //
   // NOTE: The loaded APKs are searched in reverse order.
-  std::unique_ptr<Asset> Open(const std::string& filename, Asset::AccessMode mode);
+  std::unique_ptr<Asset> Open(const std::string& filename, Asset::AccessMode mode) const;
 
   // Opens a file within the assets/ directory of the APK specified by `cookie`.
   // `mode` controls how the file is opened.
   std::unique_ptr<Asset> Open(const std::string& filename, ApkAssetsCookie cookie,
-                              Asset::AccessMode mode);
+                              Asset::AccessMode mode) const;
 
   // Opens the directory specified by `dirname`. The result is an AssetDir that is the combination
   // of all directories matching `dirname` under the assets/ directory of every ApkAssets loaded.
   // The entries are sorted by their ASCII name.
-  std::unique_ptr<AssetDir> OpenDir(const std::string& dirname);
+  std::unique_ptr<AssetDir> OpenDir(const std::string& dirname) const;
 
   // Searches the set of APKs loaded by this AssetManager and opens the first one found.
   // `mode` controls how the file is opened.
@@ -161,24 +163,24 @@
   //
   // NOTE: The loaded APKs are searched in reverse order.
   std::unique_ptr<Asset> OpenNonAsset(const std::string& filename, Asset::AccessMode mode,
-                                      ApkAssetsCookie* out_cookie = nullptr);
+                                      ApkAssetsCookie* out_cookie = nullptr) const;
 
   // Opens a file in the APK specified by `cookie`. `mode` controls how the file is opened.
   // This is typically used to open a specific AndroidManifest.xml, or a binary XML file
   // referenced by a resource lookup with GetResource().
   std::unique_ptr<Asset> OpenNonAsset(const std::string& filename, ApkAssetsCookie cookie,
-                                      Asset::AccessMode mode);
+                                      Asset::AccessMode mode) const;
 
   // Populates the `out_name` parameter with resource name information.
   // Utf8 strings are preferred, and only if they are unavailable are
   // the Utf16 variants populated.
   // Returns false if the resource was not found or the name was missing/corrupt.
-  bool GetResourceName(uint32_t resid, ResourceName* out_name);
+  bool GetResourceName(uint32_t resid, ResourceName* out_name) const;
 
   // Populates `out_flags` with the bitmask of configuration axis that this resource varies with.
   // See ResTable_config for the list of configuration axis.
   // Returns false if the resource was not found.
-  bool GetResourceFlags(uint32_t resid, uint32_t* out_flags);
+  bool GetResourceFlags(uint32_t resid, uint32_t* out_flags) const;
 
   // Finds the resource ID assigned to `resource_name`.
   // `resource_name` must be of the form '[package:][type/]entry'.
@@ -186,7 +188,7 @@
   // If no type is specified in `resource_name`, then `fallback_type` is used as the type.
   // Returns 0x0 if no resource by that name was found.
   uint32_t GetResourceId(const std::string& resource_name, const std::string& fallback_type = {},
-                         const std::string& fallback_package = {});
+                         const std::string& fallback_package = {}) const;
 
   // Retrieves the best matching resource with ID `resid`. The resource value is filled into
   // `out_value` and the configuration for the selected value is populated in `out_selected_config`.
@@ -199,7 +201,7 @@
   // this function logs if the resource was a map/bag type before returning kInvalidCookie.
   ApkAssetsCookie GetResource(uint32_t resid, bool may_be_bag, uint16_t density_override,
                               Res_value* out_value, ResTable_config* out_selected_config,
-                              uint32_t* out_flags);
+                              uint32_t* out_flags) const;
 
   // Resolves the resource reference in `in_out_value` if the data type is
   // Res_value::TYPE_REFERENCE.
@@ -215,7 +217,7 @@
   // it was not found.
   ApkAssetsCookie ResolveReference(ApkAssetsCookie cookie, Res_value* in_out_value,
                                    ResTable_config* in_out_selected_config, uint32_t* in_out_flags,
-                                   uint32_t* out_last_reference);
+                                   uint32_t* out_last_reference) const;
 
   // Retrieves the best matching bag/map resource with ID `resid`.
   // This method will resolve all parent references for this bag and merge keys with the child.
@@ -233,9 +235,9 @@
   std::unique_ptr<Theme> NewTheme();
 
   template <typename Func>
-  void ForEachPackage(Func func) {
+  void ForEachPackage(Func func) const {
     for (const PackageGroup& package_group : package_groups_) {
-      func(package_group.packages_.front()->GetPackageName(),
+      func(package_group.packages_.front().loaded_package_->GetPackageName(),
            package_group.dynamic_ref_table.mAssignedPackageId);
     }
   }
@@ -260,7 +262,7 @@
   // NOTE: FindEntry takes care of ensuring that structs within FindEntryResult have been properly
   // bounds-checked. Callers of FindEntry are free to trust the data if this method succeeds.
   ApkAssetsCookie FindEntry(uint32_t resid, uint16_t density_override, bool stop_at_first_match,
-                            FindEntryResult* out_entry);
+                            FindEntryResult* out_entry) const;
 
   // Assigns package IDs to all shared library ApkAssets.
   // Should be called whenever the ApkAssets are changed.
@@ -270,13 +272,43 @@
   // bitmask `diff`.
   void InvalidateCaches(uint32_t diff);
 
+  // Triggers the re-construction of lists of types that match the set configuration.
+  // This should always be called when mutating the AssetManager's configuration or ApkAssets set.
+  void RebuildFilterList();
+
   // The ordered list of ApkAssets to search. These are not owned by the AssetManager, and must
   // have a longer lifetime.
   std::vector<const ApkAssets*> apk_assets_;
 
+  // A collection of configurations and their associated ResTable_type that match the current
+  // AssetManager configuration.
+  struct FilteredConfigGroup {
+    std::vector<ResTable_config> configurations;
+    std::vector<const ResTable_type*> types;
+  };
+
+  // Represents an single package.
+  struct ConfiguredPackage {
+    // A pointer to the immutable, loaded package info.
+    const LoadedPackage* loaded_package_;
+
+    // A mutable AssetManager-specific list of configurations that match the AssetManager's
+    // current configuration. This is used as an optimization to avoid checking every single
+    // candidate configuration when looking up resources.
+    ByteBucketArray<FilteredConfigGroup> filtered_configs_;
+  };
+
+  // Represents a logical package, which can be made up of many individual packages. Each package
+  // in a PackageGroup shares the same package name and package ID.
   struct PackageGroup {
-    std::vector<const LoadedPackage*> packages_;
+    // The set of packages that make-up this group.
+    std::vector<ConfiguredPackage> packages_;
+
+    // The cookies associated with each package in the group. They share the same order as
+    // packages_.
     std::vector<ApkAssetsCookie> cookies_;
+
+    // A library reference table that contains build-package ID to runtime-package ID mappings.
     DynamicRefTable dynamic_ref_table;
   };
 
@@ -350,7 +382,7 @@
   ApkAssetsCookie ResolveAttributeReference(ApkAssetsCookie cookie, Res_value* in_out_value,
                                             ResTable_config* in_out_selected_config = nullptr,
                                             uint32_t* in_out_type_spec_flags = nullptr,
-                                            uint32_t* out_last_ref = nullptr);
+                                            uint32_t* out_last_ref = nullptr) const;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(Theme);
diff --git a/libs/androidfw/include/androidfw/AttributeFinder.h b/libs/androidfw/include/androidfw/AttributeFinder.h
index f281921..03fad49 100644
--- a/libs/androidfw/include/androidfw/AttributeFinder.h
+++ b/libs/androidfw/include/androidfw/AttributeFinder.h
@@ -58,6 +58,7 @@
   BackTrackingAttributeFinder(const Iterator& begin, const Iterator& end);
 
   Iterator Find(uint32_t attr);
+  inline Iterator end();
 
  private:
   void JumpToClosestAttribute(uint32_t package_id);
@@ -201,6 +202,11 @@
   return end_;
 }
 
+template <typename Derived, typename Iterator>
+Iterator BackTrackingAttributeFinder<Derived, Iterator>::end() {
+  return end_;
+}
+
 }  // namespace android
 
 #endif  // ANDROIDFW_ATTRIBUTE_FINDER_H
diff --git a/libs/androidfw/include/androidfw/AttributeResolution.h b/libs/androidfw/include/androidfw/AttributeResolution.h
index 69b76041..35ef98d 100644
--- a/libs/androidfw/include/androidfw/AttributeResolution.h
+++ b/libs/androidfw/include/androidfw/AttributeResolution.h
@@ -17,7 +17,8 @@
 #ifndef ANDROIDFW_ATTRIBUTERESOLUTION_H
 #define ANDROIDFW_ATTRIBUTERESOLUTION_H
 
-#include <androidfw/ResourceTypes.h>
+#include "androidfw/AssetManager2.h"
+#include "androidfw/ResourceTypes.h"
 
 namespace android {
 
@@ -42,19 +43,19 @@
 
 // `out_values` must NOT be nullptr.
 // `out_indices` may be nullptr.
-bool ResolveAttrs(ResTable::Theme* theme, uint32_t def_style_attr, uint32_t def_style_res,
+bool ResolveAttrs(Theme* theme, uint32_t def_style_attr, uint32_t def_style_resid,
                   uint32_t* src_values, size_t src_values_length, uint32_t* attrs,
                   size_t attrs_length, uint32_t* out_values, uint32_t* out_indices);
 
 // `out_values` must NOT be nullptr.
 // `out_indices` is NOT optional and must NOT be nullptr.
-void ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr,
-                uint32_t def_style_res, const uint32_t* attrs, size_t attrs_length,
+void ApplyStyle(Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr,
+                uint32_t def_style_resid, const uint32_t* attrs, size_t attrs_length,
                 uint32_t* out_values, uint32_t* out_indices);
 
 // `out_values` must NOT be nullptr.
 // `out_indices` may be nullptr.
-bool RetrieveAttributes(const ResTable* res, ResXMLParser* xml_parser, uint32_t* attrs,
+bool RetrieveAttributes(AssetManager2* assetmanager, ResXMLParser* xml_parser, uint32_t* attrs,
                         size_t attrs_length, uint32_t* out_values, uint32_t* out_indices);
 
 }  // namespace android
diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h
index 965e2db..35ae5fc 100644
--- a/libs/androidfw/include/androidfw/LoadedArsc.h
+++ b/libs/androidfw/include/androidfw/LoadedArsc.h
@@ -41,32 +41,40 @@
   int package_id = 0;
 };
 
-struct FindEntryResult {
-  // A pointer to the resource table entry for this resource.
-  // If the size of the entry is > sizeof(ResTable_entry), it can be cast to
-  // a ResTable_map_entry and processed as a bag/map.
-  const ResTable_entry* entry = nullptr;
+// TypeSpec is going to be immediately proceeded by
+// an array of Type structs, all in the same block of memory.
+struct TypeSpec {
+  // Pointer to the mmapped data where flags are kept.
+  // Flags denote whether the resource entry is public
+  // and under which configurations it varies.
+  const ResTable_typeSpec* type_spec;
 
-  // The configuration for which the resulting entry was defined.
-  const ResTable_config* config = nullptr;
+  // Pointer to the mmapped data where the IDMAP mappings for this type
+  // exist. May be nullptr if no IDMAP exists.
+  const IdmapEntry_header* idmap_entries;
 
-  // Stores the resulting bitmask of configuration axis with which the resource value varies.
-  uint32_t type_flags = 0u;
+  // The number of types that follow this struct.
+  // There is a type for each configuration that entries are defined for.
+  size_t type_count;
 
-  // The dynamic package ID map for the package from which this resource came from.
-  const DynamicRefTable* dynamic_ref_table = nullptr;
+  // Trick to easily access a variable number of Type structs
+  // proceeding this struct, and to ensure their alignment.
+  const ResTable_type* types[0];
 
-  // The string pool reference to the type's name. This uses a different string pool than
-  // the global string pool, but this is hidden from the caller.
-  StringPoolRef type_string_ref;
+  inline uint32_t GetFlagsForEntryIndex(uint16_t entry_index) const {
+    if (entry_index >= dtohl(type_spec->entryCount)) {
+      return 0u;
+    }
 
-  // The string pool reference to the entry's name. This uses a different string pool than
-  // the global string pool, but this is hidden from the caller.
-  StringPoolRef entry_string_ref;
+    const uint32_t* flags = reinterpret_cast<const uint32_t*>(type_spec + 1);
+    return flags[entry_index];
+  }
 };
 
-struct TypeSpec;
-class LoadedArsc;
+// TypeSpecPtr points to a block of memory that holds a TypeSpec struct, followed by an array of
+// ResTable_type pointers.
+// TypeSpecPtr is a managed pointer that knows how to delete itself.
+using TypeSpecPtr = util::unique_cptr<TypeSpec>;
 
 class LoadedPackage {
  public:
@@ -76,9 +84,6 @@
 
   ~LoadedPackage();
 
-  bool FindEntry(uint8_t type_idx, uint16_t entry_idx, const ResTable_config& config,
-                 FindEntryResult* out_entry) const;
-
   // Finds the entry with the specified type name and entry name. The names are in UTF-16 because
   // the underlying ResStringPool API expects this. For now this is acceptable, but since
   // the default policy in AAPT2 is to build UTF-8 string pools, this needs to change.
@@ -86,6 +91,12 @@
   // for patching the correct package ID to the resource ID.
   uint32_t FindEntryByName(const std::u16string& type_name, const std::u16string& entry_name) const;
 
+  static const ResTable_entry* GetEntry(const ResTable_type* type_chunk, uint16_t entry_index);
+
+  static uint32_t GetEntryOffset(const ResTable_type* type_chunk, uint16_t entry_index);
+
+  static const ResTable_entry* GetEntryFromOffset(const ResTable_type* type_chunk, uint32_t offset);
+
   // Returns the string pool where type names are stored.
   inline const ResStringPool* GetTypeStringPool() const {
     return &type_string_pool_;
@@ -135,14 +146,32 @@
   // before being inserted into the set. This may cause some equivalent locales to de-dupe.
   void CollectLocales(bool canonicalize, std::set<std::string>* out_locales) const;
 
+  // type_idx is TT - 1 from 0xPPTTEEEE.
+  inline const TypeSpec* GetTypeSpecByTypeIndex(uint8_t type_index) const {
+    // If the type IDs are offset in this package, we need to take that into account when searching
+    // for a type.
+    return type_specs_[type_index - type_id_offset_].get();
+  }
+
+  template <typename Func>
+  void ForEachTypeSpec(Func f) const {
+    for (size_t i = 0; i < type_specs_.size(); i++) {
+      const TypeSpecPtr& ptr = type_specs_[i];
+      if (ptr != nullptr) {
+        uint8_t type_id = ptr->type_spec->id;
+        if (ptr->idmap_entries != nullptr) {
+          type_id = ptr->idmap_entries->target_type_id;
+        }
+        f(ptr.get(), type_id - 1);
+      }
+    }
+  }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(LoadedPackage);
 
   LoadedPackage();
 
-  bool FindEntry(const util::unique_cptr<TypeSpec>& type_spec_ptr, uint16_t entry_idx,
-                 const ResTable_config& config, FindEntryResult* out_entry) const;
-
   ResStringPool type_string_pool_;
   ResStringPool key_string_pool_;
   std::string package_name_;
@@ -152,7 +181,7 @@
   bool system_ = false;
   bool overlay_ = false;
 
-  ByteBucketArray<util::unique_cptr<TypeSpec>> type_specs_;
+  ByteBucketArray<TypeSpecPtr> type_specs_;
   std::vector<DynamicPackageEntry> dynamic_package_map_;
 };
 
@@ -180,25 +209,20 @@
     return &global_string_pool_;
   }
 
-  // Finds the resource with ID `resid` with the best value for configuration `config`.
-  // The parameter `out_entry` will be filled with the resulting resource entry.
-  // The resource entry can be a simple entry (ResTable_entry) or a complex bag
-  // (ResTable_entry_map).
-  bool FindEntry(uint32_t resid, const ResTable_config& config, FindEntryResult* out_entry) const;
-
-  // Gets a pointer to the name of the package in `resid`, or nullptr if the package doesn't exist.
-  const LoadedPackage* GetPackageForId(uint32_t resid) const;
-
-  // Returns true if this is a system provided resource.
-  inline bool IsSystem() const {
-    return system_;
-  }
+  // Gets a pointer to the package with the specified package ID, or nullptr if no such package
+  // exists.
+  const LoadedPackage* GetPackageById(uint8_t package_id) const;
 
   // Returns a vector of LoadedPackage pointers, representing the packages in this LoadedArsc.
   inline const std::vector<std::unique_ptr<const LoadedPackage>>& GetPackages() const {
     return packages_;
   }
 
+  // Returns true if this is a system provided resource.
+  inline bool IsSystem() const {
+    return system_;
+  }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(LoadedArsc);
 
diff --git a/libs/androidfw/include/androidfw/MutexGuard.h b/libs/androidfw/include/androidfw/MutexGuard.h
new file mode 100644
index 0000000..64924f4
--- /dev/null
+++ b/libs/androidfw/include/androidfw/MutexGuard.h
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROIDFW_MUTEXGUARD_H
+#define ANDROIDFW_MUTEXGUARD_H
+
+#include <mutex>
+#include <type_traits>
+
+#include "android-base/macros.h"
+
+namespace android {
+
+template <typename T>
+class ScopedLock;
+
+// Owns the guarded object and protects access to it via a mutex.
+// The guarded object is inaccessible via this class.
+// The mutex is locked and the object accessed via the ScopedLock<T> class.
+//
+// NOTE: The template parameter T should not be a raw pointer, since ownership
+// is ambiguous and error-prone. Instead use an std::unique_ptr<>.
+//
+// Example use:
+//
+//   Guarded<std::string> shared_string("hello");
+//   {
+//     ScopedLock<std::string> locked_string(shared_string);
+//     *locked_string += " world";
+//   }
+//
+template <typename T>
+class Guarded {
+  static_assert(!std::is_pointer<T>::value, "T must not be a raw pointer");
+
+ public:
+  explicit Guarded() : guarded_() {
+  }
+
+  template <typename U = T>
+  explicit Guarded(const T& guarded,
+                   typename std::enable_if<std::is_copy_constructible<U>::value>::type = void())
+      : guarded_(guarded) {
+  }
+
+  template <typename U = T>
+  explicit Guarded(T&& guarded,
+                   typename std::enable_if<std::is_move_constructible<U>::value>::type = void())
+      : guarded_(std::move(guarded)) {
+  }
+
+ private:
+  friend class ScopedLock<T>;
+
+  DISALLOW_COPY_AND_ASSIGN(Guarded);
+
+  std::mutex lock_;
+  T guarded_;
+};
+
+template <typename T>
+class ScopedLock {
+ public:
+  explicit ScopedLock(Guarded<T>& guarded) : lock_(guarded.lock_), guarded_(guarded.guarded_) {
+  }
+
+  T& operator*() {
+    return guarded_;
+  }
+
+  T* operator->() {
+    return &guarded_;
+  }
+
+  T* get() {
+    return &guarded_;
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ScopedLock);
+
+  std::lock_guard<std::mutex> lock_;
+  T& guarded_;
+};
+
+}  // namespace android
+
+#endif  // ANDROIDFW_MUTEXGUARD_H
diff --git a/libs/androidfw/include/androidfw/ResourceUtils.h b/libs/androidfw/include/androidfw/ResourceUtils.h
index c2eae85..d94779b 100644
--- a/libs/androidfw/include/androidfw/ResourceUtils.h
+++ b/libs/androidfw/include/androidfw/ResourceUtils.h
@@ -28,7 +28,7 @@
                          StringPiece* out_entry);
 
 inline uint32_t fix_package_id(uint32_t resid, uint8_t package_id) {
-  return resid | (static_cast<uint32_t>(package_id) << 24);
+  return (resid & 0x00ffffffu) | (static_cast<uint32_t>(package_id) << 24);
 }
 
 inline uint8_t get_package_id(uint32_t resid) {
diff --git a/libs/androidfw/tests/ApkAssets_test.cpp b/libs/androidfw/tests/ApkAssets_test.cpp
index 6c43a67..e2b9f00 100644
--- a/libs/androidfw/tests/ApkAssets_test.cpp
+++ b/libs/androidfw/tests/ApkAssets_test.cpp
@@ -26,58 +26,56 @@
 
 using ::android::base::unique_fd;
 using ::com::android::basic::R;
+using ::testing::Eq;
+using ::testing::Ge;
+using ::testing::NotNull;
+using ::testing::SizeIs;
+using ::testing::StrEq;
 
 namespace android {
 
 TEST(ApkAssetsTest, LoadApk) {
   std::unique_ptr<const ApkAssets> loaded_apk =
       ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
-  ASSERT_NE(nullptr, loaded_apk);
+  ASSERT_THAT(loaded_apk, NotNull());
 
   const LoadedArsc* loaded_arsc = loaded_apk->GetLoadedArsc();
-  ASSERT_NE(nullptr, loaded_arsc);
-
-  const LoadedPackage* loaded_package = loaded_arsc->GetPackageForId(0x7f010000);
-  ASSERT_NE(nullptr, loaded_package);
-
-  std::unique_ptr<Asset> asset = loaded_apk->Open("res/layout/main.xml");
-  ASSERT_NE(nullptr, asset);
+  ASSERT_THAT(loaded_arsc, NotNull());
+  ASSERT_THAT(loaded_arsc->GetPackageById(0x7fu), NotNull());
+  ASSERT_THAT(loaded_apk->Open("res/layout/main.xml"), NotNull());
 }
 
 TEST(ApkAssetsTest, LoadApkFromFd) {
   const std::string path = GetTestDataPath() + "/basic/basic.apk";
   unique_fd fd(::open(path.c_str(), O_RDONLY | O_BINARY));
-  ASSERT_GE(fd.get(), 0);
+  ASSERT_THAT(fd.get(), Ge(0));
 
   std::unique_ptr<const ApkAssets> loaded_apk =
       ApkAssets::LoadFromFd(std::move(fd), path, false /*system*/, false /*force_shared_lib*/);
-  ASSERT_NE(nullptr, loaded_apk);
+  ASSERT_THAT(loaded_apk, NotNull());
 
   const LoadedArsc* loaded_arsc = loaded_apk->GetLoadedArsc();
-  ASSERT_NE(nullptr, loaded_arsc);
-
-  const LoadedPackage* loaded_package = loaded_arsc->GetPackageForId(0x7f010000);
-  ASSERT_NE(nullptr, loaded_package);
-
-  std::unique_ptr<Asset> asset = loaded_apk->Open("res/layout/main.xml");
-  ASSERT_NE(nullptr, asset);
+  ASSERT_THAT(loaded_arsc, NotNull());
+  ASSERT_THAT(loaded_arsc->GetPackageById(0x7fu), NotNull());
+  ASSERT_THAT(loaded_apk->Open("res/layout/main.xml"), NotNull());
 }
 
 TEST(ApkAssetsTest, LoadApkAsSharedLibrary) {
   std::unique_ptr<const ApkAssets> loaded_apk =
       ApkAssets::Load(GetTestDataPath() + "/appaslib/appaslib.apk");
-  ASSERT_NE(nullptr, loaded_apk);
+  ASSERT_THAT(loaded_apk, NotNull());
+
   const LoadedArsc* loaded_arsc = loaded_apk->GetLoadedArsc();
-  ASSERT_NE(nullptr, loaded_arsc);
-  ASSERT_EQ(1u, loaded_arsc->GetPackages().size());
+  ASSERT_THAT(loaded_arsc, NotNull());
+  ASSERT_THAT(loaded_arsc->GetPackages(), SizeIs(1u));
   EXPECT_FALSE(loaded_arsc->GetPackages()[0]->IsDynamic());
 
   loaded_apk = ApkAssets::LoadAsSharedLibrary(GetTestDataPath() + "/appaslib/appaslib.apk");
-  ASSERT_NE(nullptr, loaded_apk);
+  ASSERT_THAT(loaded_apk, NotNull());
 
   loaded_arsc = loaded_apk->GetLoadedArsc();
-  ASSERT_NE(nullptr, loaded_arsc);
-  ASSERT_EQ(1u, loaded_arsc->GetPackages().size());
+  ASSERT_THAT(loaded_arsc, NotNull());
+  ASSERT_THAT(loaded_arsc->GetPackages(), SizeIs(1u));
   EXPECT_TRUE(loaded_arsc->GetPackages()[0]->IsDynamic());
 }
 
@@ -86,19 +84,22 @@
   ResTable target_table;
   const std::string target_path = GetTestDataPath() + "/basic/basic.apk";
   ASSERT_TRUE(ReadFileFromZipToString(target_path, "resources.arsc", &contents));
-  ASSERT_EQ(NO_ERROR, target_table.add(contents.data(), contents.size(), 0, true /*copyData*/));
+  ASSERT_THAT(target_table.add(contents.data(), contents.size(), 0, true /*copyData*/),
+              Eq(NO_ERROR));
 
   ResTable overlay_table;
   const std::string overlay_path = GetTestDataPath() + "/overlay/overlay.apk";
   ASSERT_TRUE(ReadFileFromZipToString(overlay_path, "resources.arsc", &contents));
-  ASSERT_EQ(NO_ERROR, overlay_table.add(contents.data(), contents.size(), 0, true /*copyData*/));
+  ASSERT_THAT(overlay_table.add(contents.data(), contents.size(), 0, true /*copyData*/),
+              Eq(NO_ERROR));
 
   util::unique_cptr<void> idmap_data;
   void* temp_data;
   size_t idmap_len;
 
-  ASSERT_EQ(NO_ERROR, target_table.createIdmap(overlay_table, 0u, 0u, target_path.c_str(),
-                                               overlay_path.c_str(), &temp_data, &idmap_len));
+  ASSERT_THAT(target_table.createIdmap(overlay_table, 0u, 0u, target_path.c_str(),
+                                       overlay_path.c_str(), &temp_data, &idmap_len),
+              Eq(NO_ERROR));
   idmap_data.reset(temp_data);
 
   TemporaryFile tf;
@@ -108,37 +109,30 @@
   // Open something so that the destructor of TemporaryFile closes a valid fd.
   tf.fd = open("/dev/null", O_WRONLY);
 
-  std::unique_ptr<const ApkAssets> loaded_overlay_apk = ApkAssets::LoadOverlay(tf.path);
-  ASSERT_NE(nullptr, loaded_overlay_apk);
+  ASSERT_THAT(ApkAssets::LoadOverlay(tf.path), NotNull());
 }
 
 TEST(ApkAssetsTest, CreateAndDestroyAssetKeepsApkAssetsOpen) {
   std::unique_ptr<const ApkAssets> loaded_apk =
       ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
-  ASSERT_NE(nullptr, loaded_apk);
+  ASSERT_THAT(loaded_apk, NotNull());
 
-  {
-    std::unique_ptr<Asset> assets = loaded_apk->Open("res/layout/main.xml", Asset::ACCESS_BUFFER);
-    ASSERT_NE(nullptr, assets);
-  }
+  { ASSERT_THAT(loaded_apk->Open("res/layout/main.xml", Asset::ACCESS_BUFFER), NotNull()); }
 
-  {
-    std::unique_ptr<Asset> assets = loaded_apk->Open("res/layout/main.xml", Asset::ACCESS_BUFFER);
-    ASSERT_NE(nullptr, assets);
-  }
+  { ASSERT_THAT(loaded_apk->Open("res/layout/main.xml", Asset::ACCESS_BUFFER), NotNull()); }
 }
 
 TEST(ApkAssetsTest, OpenUncompressedAssetFd) {
   std::unique_ptr<const ApkAssets> loaded_apk =
       ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
-  ASSERT_NE(nullptr, loaded_apk);
+  ASSERT_THAT(loaded_apk, NotNull());
 
   auto asset = loaded_apk->Open("assets/uncompressed.txt", Asset::ACCESS_UNKNOWN);
-  ASSERT_NE(nullptr, asset);
+  ASSERT_THAT(asset, NotNull());
 
   off64_t start, length;
   unique_fd fd(asset->openFileDescriptor(&start, &length));
-  EXPECT_GE(fd.get(), 0);
+  ASSERT_THAT(fd.get(), Ge(0));
 
   lseek64(fd.get(), start, SEEK_SET);
 
@@ -146,7 +140,7 @@
   buffer.resize(length);
   ASSERT_TRUE(base::ReadFully(fd.get(), &*buffer.begin(), length));
 
-  EXPECT_EQ("This should be uncompressed.\n\n", buffer);
+  EXPECT_THAT(buffer, StrEq("This should be uncompressed.\n\n"));
 }
 
 }  // namespace android
diff --git a/libs/androidfw/tests/AssetManager2_bench.cpp b/libs/androidfw/tests/AssetManager2_bench.cpp
index 85e8f25..437e147 100644
--- a/libs/androidfw/tests/AssetManager2_bench.cpp
+++ b/libs/androidfw/tests/AssetManager2_bench.cpp
@@ -81,17 +81,18 @@
 }
 BENCHMARK(BM_AssetManagerLoadFrameworkAssetsOld);
 
-static void BM_AssetManagerGetResource(benchmark::State& state) {
-  GetResourceBenchmark({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/,
-                       basic::R::integer::number1, state);
+static void BM_AssetManagerGetResource(benchmark::State& state, uint32_t resid) {
+  GetResourceBenchmark({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/, resid, state);
 }
-BENCHMARK(BM_AssetManagerGetResource);
+BENCHMARK_CAPTURE(BM_AssetManagerGetResource, number1, basic::R::integer::number1);
+BENCHMARK_CAPTURE(BM_AssetManagerGetResource, deep_ref, basic::R::integer::deep_ref);
 
-static void BM_AssetManagerGetResourceOld(benchmark::State& state) {
-  GetResourceBenchmarkOld({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/,
-                          basic::R::integer::number1, state);
+static void BM_AssetManagerGetResourceOld(benchmark::State& state, uint32_t resid) {
+  GetResourceBenchmarkOld({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/, resid,
+                          state);
 }
-BENCHMARK(BM_AssetManagerGetResourceOld);
+BENCHMARK_CAPTURE(BM_AssetManagerGetResourceOld, number1, basic::R::integer::number1);
+BENCHMARK_CAPTURE(BM_AssetManagerGetResourceOld, deep_ref, basic::R::integer::deep_ref);
 
 static void BM_AssetManagerGetLibraryResource(benchmark::State& state) {
   GetResourceBenchmark(
@@ -196,7 +197,7 @@
 static void BM_AssetManagerGetResourceLocalesOld(benchmark::State& state) {
   AssetManager assets;
   if (!assets.addAssetPath(String8(kFrameworkPath), nullptr /*cookie*/, false /*appAsLib*/,
-                           false /*isSystemAssets*/)) {
+                           true /*isSystemAssets*/)) {
     state.SkipWithError("Failed to load assets");
     return;
   }
@@ -211,4 +212,44 @@
 }
 BENCHMARK(BM_AssetManagerGetResourceLocalesOld);
 
+static void BM_AssetManagerSetConfigurationFramework(benchmark::State& state) {
+  std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(kFrameworkPath);
+  if (apk == nullptr) {
+    state.SkipWithError("Failed to load assets");
+    return;
+  }
+
+  AssetManager2 assets;
+  assets.SetApkAssets({apk.get()});
+
+  ResTable_config config;
+  memset(&config, 0, sizeof(config));
+
+  while (state.KeepRunning()) {
+    config.sdkVersion = ~config.sdkVersion;
+    assets.SetConfiguration(config);
+  }
+}
+BENCHMARK(BM_AssetManagerSetConfigurationFramework);
+
+static void BM_AssetManagerSetConfigurationFrameworkOld(benchmark::State& state) {
+  AssetManager assets;
+  if (!assets.addAssetPath(String8(kFrameworkPath), nullptr /*cookie*/, false /*appAsLib*/,
+                           true /*isSystemAssets*/)) {
+    state.SkipWithError("Failed to load assets");
+    return;
+  }
+
+  const ResTable& table = assets.getResources(true);
+
+  ResTable_config config;
+  memset(&config, 0, sizeof(config));
+
+  while (state.KeepRunning()) {
+    config.sdkVersion = ~config.sdkVersion;
+    assets.setConfiguration(config);
+  }
+}
+BENCHMARK(BM_AssetManagerSetConfigurationFrameworkOld);
+
 }  // namespace android
diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp
index 92462a6..7cac2b3 100644
--- a/libs/androidfw/tests/AssetManager2_test.cpp
+++ b/libs/androidfw/tests/AssetManager2_test.cpp
@@ -36,6 +36,10 @@
 namespace lib_two = com::android::lib_two;
 namespace libclient = com::android::libclient;
 
+using ::testing::Eq;
+using ::testing::NotNull;
+using ::testing::StrEq;
+
 namespace android {
 
 class AssetManager2Test : public ::testing::Test {
@@ -59,11 +63,14 @@
     libclient_assets_ = ApkAssets::Load(GetTestDataPath() + "/libclient/libclient.apk");
     ASSERT_NE(nullptr, libclient_assets_);
 
-    appaslib_assets_ = ApkAssets::Load(GetTestDataPath() + "/appaslib/appaslib.apk");
+    appaslib_assets_ = ApkAssets::LoadAsSharedLibrary(GetTestDataPath() + "/appaslib/appaslib.apk");
     ASSERT_NE(nullptr, appaslib_assets_);
 
     system_assets_ = ApkAssets::Load(GetTestDataPath() + "/system/system.apk", true /*system*/);
     ASSERT_NE(nullptr, system_assets_);
+
+    app_assets_ = ApkAssets::Load(GetTestDataPath() + "/app/app.apk");
+    ASSERT_THAT(app_assets_, NotNull());
   }
 
  protected:
@@ -75,6 +82,7 @@
   std::unique_ptr<const ApkAssets> libclient_assets_;
   std::unique_ptr<const ApkAssets> appaslib_assets_;
   std::unique_ptr<const ApkAssets> system_assets_;
+  std::unique_ptr<const ApkAssets> app_assets_;
 };
 
 TEST_F(AssetManager2Test, FindsResourceFromSingleApkAssets) {
@@ -233,6 +241,25 @@
   assetmanager.SetApkAssets(
       {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()});
 
+  const ResolvedBag* bag = assetmanager.GetBag(fix_package_id(lib_one::R::style::Theme, 0x03));
+  ASSERT_NE(nullptr, bag);
+  ASSERT_GE(bag->entry_count, 2u);
+
+  // First two attributes come from lib_one.
+  EXPECT_EQ(1, bag->entries[0].cookie);
+  EXPECT_EQ(0x03, get_package_id(bag->entries[0].key));
+  EXPECT_EQ(1, bag->entries[1].cookie);
+  EXPECT_EQ(0x03, get_package_id(bag->entries[1].key));
+}
+
+TEST_F(AssetManager2Test, FindsStyleResourceWithParentFromSharedLibrary) {
+  AssetManager2 assetmanager;
+
+  // libclient is built with lib_one and then lib_two in order.
+  // Reverse the order to test that proper package ID re-assignment is happening.
+  assetmanager.SetApkAssets(
+      {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()});
+
   const ResolvedBag* bag = assetmanager.GetBag(libclient::R::style::Theme);
   ASSERT_NE(nullptr, bag);
   ASSERT_GE(bag->entry_count, 2u);
@@ -446,8 +473,68 @@
             assetmanager.GetResourceId("main", "layout", "com.android.basic"));
 }
 
-TEST_F(AssetManager2Test, OpensFileFromSingleApkAssets) {}
+TEST_F(AssetManager2Test, OpensFileFromSingleApkAssets) {
+  AssetManager2 assetmanager;
+  assetmanager.SetApkAssets({system_assets_.get()});
 
-TEST_F(AssetManager2Test, OpensFileFromMultipleApkAssets) {}
+  std::unique_ptr<Asset> asset = assetmanager.Open("file.txt", Asset::ACCESS_BUFFER);
+  ASSERT_THAT(asset, NotNull());
+
+  const char* data = reinterpret_cast<const char*>(asset->getBuffer(false /*wordAligned*/));
+  ASSERT_THAT(data, NotNull());
+  EXPECT_THAT(std::string(data, asset->getLength()), StrEq("file\n"));
+}
+
+TEST_F(AssetManager2Test, OpensFileFromMultipleApkAssets) {
+  AssetManager2 assetmanager;
+  assetmanager.SetApkAssets({system_assets_.get(), app_assets_.get()});
+
+  std::unique_ptr<Asset> asset = assetmanager.Open("file.txt", Asset::ACCESS_BUFFER);
+  ASSERT_THAT(asset, NotNull());
+
+  const char* data = reinterpret_cast<const char*>(asset->getBuffer(false /*wordAligned*/));
+  ASSERT_THAT(data, NotNull());
+  EXPECT_THAT(std::string(data, asset->getLength()), StrEq("app override file\n"));
+}
+
+TEST_F(AssetManager2Test, OpenDir) {
+  AssetManager2 assetmanager;
+  assetmanager.SetApkAssets({system_assets_.get()});
+
+  std::unique_ptr<AssetDir> asset_dir = assetmanager.OpenDir("");
+  ASSERT_THAT(asset_dir, NotNull());
+  ASSERT_THAT(asset_dir->getFileCount(), Eq(2u));
+
+  EXPECT_THAT(asset_dir->getFileName(0), Eq(String8("file.txt")));
+  EXPECT_THAT(asset_dir->getFileType(0), Eq(FileType::kFileTypeRegular));
+
+  EXPECT_THAT(asset_dir->getFileName(1), Eq(String8("subdir")));
+  EXPECT_THAT(asset_dir->getFileType(1), Eq(FileType::kFileTypeDirectory));
+
+  asset_dir = assetmanager.OpenDir("subdir");
+  ASSERT_THAT(asset_dir, NotNull());
+  ASSERT_THAT(asset_dir->getFileCount(), Eq(1u));
+
+  EXPECT_THAT(asset_dir->getFileName(0), Eq(String8("subdir_file.txt")));
+  EXPECT_THAT(asset_dir->getFileType(0), Eq(FileType::kFileTypeRegular));
+}
+
+TEST_F(AssetManager2Test, OpenDirFromManyApks) {
+  AssetManager2 assetmanager;
+  assetmanager.SetApkAssets({system_assets_.get(), app_assets_.get()});
+
+  std::unique_ptr<AssetDir> asset_dir = assetmanager.OpenDir("");
+  ASSERT_THAT(asset_dir, NotNull());
+  ASSERT_THAT(asset_dir->getFileCount(), Eq(3u));
+
+  EXPECT_THAT(asset_dir->getFileName(0), Eq(String8("app_file.txt")));
+  EXPECT_THAT(asset_dir->getFileType(0), Eq(FileType::kFileTypeRegular));
+
+  EXPECT_THAT(asset_dir->getFileName(1), Eq(String8("file.txt")));
+  EXPECT_THAT(asset_dir->getFileType(1), Eq(FileType::kFileTypeRegular));
+
+  EXPECT_THAT(asset_dir->getFileName(2), Eq(String8("subdir")));
+  EXPECT_THAT(asset_dir->getFileType(2), Eq(FileType::kFileTypeDirectory));
+}
 
 }  // namespace android
diff --git a/libs/androidfw/tests/AttributeResolution_bench.cpp b/libs/androidfw/tests/AttributeResolution_bench.cpp
new file mode 100644
index 0000000..fa300c5
--- /dev/null
+++ b/libs/androidfw/tests/AttributeResolution_bench.cpp
@@ -0,0 +1,175 @@
+/*
+ * 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 "benchmark/benchmark.h"
+
+//#include "android-base/stringprintf.h"
+#include "androidfw/ApkAssets.h"
+#include "androidfw/AssetManager.h"
+#include "androidfw/AssetManager2.h"
+#include "androidfw/AttributeResolution.h"
+#include "androidfw/ResourceTypes.h"
+
+#include "BenchmarkHelpers.h"
+#include "data/basic/R.h"
+#include "data/styles/R.h"
+
+namespace app = com::android::app;
+namespace basic = com::android::basic;
+
+namespace android {
+
+constexpr const static char* kFrameworkPath = "/system/framework/framework-res.apk";
+constexpr const static uint32_t Theme_Material_Light = 0x01030237u;
+
+static void BM_ApplyStyle(benchmark::State& state) {
+  std::unique_ptr<const ApkAssets> styles_apk =
+      ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
+  if (styles_apk == nullptr) {
+    state.SkipWithError("failed to load assets");
+    return;
+  }
+
+  AssetManager2 assetmanager;
+  assetmanager.SetApkAssets({styles_apk.get()});
+
+  std::unique_ptr<Asset> asset =
+      assetmanager.OpenNonAsset("res/layout/layout.xml", Asset::ACCESS_BUFFER);
+  if (asset == nullptr) {
+    state.SkipWithError("failed to load layout");
+    return;
+  }
+
+  ResXMLTree xml_tree;
+  if (xml_tree.setTo(asset->getBuffer(true), asset->getLength(), false /*copyData*/) != NO_ERROR) {
+    state.SkipWithError("corrupt xml layout");
+    return;
+  }
+
+  // Skip to the first tag.
+  while (xml_tree.next() != ResXMLParser::START_TAG) {
+  }
+
+  std::unique_ptr<Theme> theme = assetmanager.NewTheme();
+  theme->ApplyStyle(app::R::style::StyleTwo);
+
+  std::array<uint32_t, 6> attrs{{app::R::attr::attr_one, app::R::attr::attr_two,
+                                 app::R::attr::attr_three, app::R::attr::attr_four,
+                                 app::R::attr::attr_five, app::R::attr::attr_empty}};
+  std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
+  std::array<uint32_t, attrs.size() + 1> indices;
+
+  while (state.KeepRunning()) {
+    ApplyStyle(theme.get(), &xml_tree, 0u /*def_style_attr*/, 0u /*def_style_res*/, attrs.data(),
+               attrs.size(), values.data(), indices.data());
+  }
+}
+BENCHMARK(BM_ApplyStyle);
+
+static void BM_ApplyStyleFramework(benchmark::State& state) {
+  std::unique_ptr<const ApkAssets> framework_apk = ApkAssets::Load(kFrameworkPath);
+  if (framework_apk == nullptr) {
+    state.SkipWithError("failed to load framework assets");
+    return;
+  }
+
+  std::unique_ptr<const ApkAssets> basic_apk =
+      ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
+  if (basic_apk == nullptr) {
+    state.SkipWithError("failed to load assets");
+    return;
+  }
+
+  AssetManager2 assetmanager;
+  assetmanager.SetApkAssets({framework_apk.get(), basic_apk.get()});
+
+  ResTable_config device_config;
+  memset(&device_config, 0, sizeof(device_config));
+  device_config.language[0] = 'e';
+  device_config.language[1] = 'n';
+  device_config.country[0] = 'U';
+  device_config.country[1] = 'S';
+  device_config.orientation = ResTable_config::ORIENTATION_PORT;
+  device_config.smallestScreenWidthDp = 700;
+  device_config.screenWidthDp = 700;
+  device_config.screenHeightDp = 1024;
+  device_config.sdkVersion = 27;
+
+  Res_value value;
+  ResTable_config config;
+  uint32_t flags = 0u;
+  ApkAssetsCookie cookie =
+      assetmanager.GetResource(basic::R::layout::layoutt, false /*may_be_bag*/,
+                               0u /*density_override*/, &value, &config, &flags);
+  if (cookie == kInvalidCookie) {
+    state.SkipWithError("failed to find R.layout.layout");
+    return;
+  }
+
+  size_t len = 0u;
+  const char* layout_path =
+      assetmanager.GetStringPoolForCookie(cookie)->string8At(value.data, &len);
+  if (layout_path == nullptr || len == 0u) {
+    state.SkipWithError("failed to lookup layout path");
+    return;
+  }
+
+  std::unique_ptr<Asset> asset = assetmanager.OpenNonAsset(
+      StringPiece(layout_path, len).to_string(), cookie, Asset::ACCESS_BUFFER);
+  if (asset == nullptr) {
+    state.SkipWithError("failed to load layout");
+    return;
+  }
+
+  ResXMLTree xml_tree;
+  if (xml_tree.setTo(asset->getBuffer(true), asset->getLength(), false /*copyData*/) != NO_ERROR) {
+    state.SkipWithError("corrupt xml layout");
+    return;
+  }
+
+  // Skip to the first tag.
+  while (xml_tree.next() != ResXMLParser::START_TAG) {
+  }
+
+  std::unique_ptr<Theme> theme = assetmanager.NewTheme();
+  theme->ApplyStyle(Theme_Material_Light);
+
+  std::array<uint32_t, 92> attrs{
+      {0x0101000e, 0x01010034, 0x01010095, 0x01010096, 0x01010097, 0x01010098, 0x01010099,
+       0x0101009a, 0x0101009b, 0x010100ab, 0x010100af, 0x010100b0, 0x010100b1, 0x0101011f,
+       0x01010120, 0x0101013f, 0x01010140, 0x0101014e, 0x0101014f, 0x01010150, 0x01010151,
+       0x01010152, 0x01010153, 0x01010154, 0x01010155, 0x01010156, 0x01010157, 0x01010158,
+       0x01010159, 0x0101015a, 0x0101015b, 0x0101015c, 0x0101015d, 0x0101015e, 0x0101015f,
+       0x01010160, 0x01010161, 0x01010162, 0x01010163, 0x01010164, 0x01010165, 0x01010166,
+       0x01010167, 0x01010168, 0x01010169, 0x0101016a, 0x0101016b, 0x0101016c, 0x0101016d,
+       0x0101016e, 0x0101016f, 0x01010170, 0x01010171, 0x01010217, 0x01010218, 0x0101021d,
+       0x01010220, 0x01010223, 0x01010224, 0x01010264, 0x01010265, 0x01010266, 0x010102c5,
+       0x010102c6, 0x010102c7, 0x01010314, 0x01010315, 0x01010316, 0x0101035e, 0x0101035f,
+       0x01010362, 0x01010374, 0x0101038c, 0x01010392, 0x01010393, 0x010103ac, 0x0101045d,
+       0x010104b6, 0x010104b7, 0x010104d6, 0x010104d7, 0x010104dd, 0x010104de, 0x010104df,
+       0x01010535, 0x01010536, 0x01010537, 0x01010538, 0x01010546, 0x01010567, 0x011100c9,
+       0x011100ca}};
+
+  std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
+  std::array<uint32_t, attrs.size() + 1> indices;
+  while (state.KeepRunning()) {
+    ApplyStyle(theme.get(), &xml_tree, 0x01010084u /*def_style_attr*/, 0u /*def_style_res*/,
+               attrs.data(), attrs.size(), values.data(), indices.data());
+  }
+}
+BENCHMARK(BM_ApplyStyleFramework);
+
+}  // namespace android
diff --git a/libs/androidfw/tests/AttributeResolution_test.cpp b/libs/androidfw/tests/AttributeResolution_test.cpp
index 2d73ce8..c8dbe20 100644
--- a/libs/androidfw/tests/AttributeResolution_test.cpp
+++ b/libs/androidfw/tests/AttributeResolution_test.cpp
@@ -21,6 +21,8 @@
 #include "android-base/file.h"
 #include "android-base/logging.h"
 #include "android-base/macros.h"
+#include "androidfw/AssetManager2.h"
+#include "androidfw/ResourceUtils.h"
 
 #include "TestHelpers.h"
 #include "data/styles/R.h"
@@ -32,15 +34,14 @@
 class AttributeResolutionTest : public ::testing::Test {
  public:
   virtual void SetUp() override {
-    std::string contents;
-    ASSERT_TRUE(ReadFileFromZipToString(
-        GetTestDataPath() + "/styles/styles.apk", "resources.arsc", &contents));
-    ASSERT_EQ(NO_ERROR, table_.add(contents.data(), contents.size(),
-                                   1 /*cookie*/, true /*copyData*/));
+    styles_assets_ = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
+    ASSERT_NE(nullptr, styles_assets_);
+    assetmanager_.SetApkAssets({styles_assets_.get()});
   }
 
  protected:
-  ResTable table_;
+  std::unique_ptr<const ApkAssets> styles_assets_;
+  AssetManager2 assetmanager_;
 };
 
 class AttributeResolutionXmlTest : public AttributeResolutionTest {
@@ -48,13 +49,12 @@
   virtual void SetUp() override {
     AttributeResolutionTest::SetUp();
 
-    std::string contents;
-    ASSERT_TRUE(
-        ReadFileFromZipToString(GetTestDataPath() + "/styles/styles.apk",
-                                "res/layout/layout.xml", &contents));
+    std::unique_ptr<Asset> asset =
+        assetmanager_.OpenNonAsset("res/layout/layout.xml", Asset::ACCESS_BUFFER);
+    ASSERT_NE(nullptr, asset);
 
-    ASSERT_EQ(NO_ERROR, xml_parser_.setTo(contents.data(), contents.size(),
-                                          true /*copyData*/));
+    ASSERT_EQ(NO_ERROR,
+              xml_parser_.setTo(asset->getBuffer(true), asset->getLength(), true /*copyData*/));
 
     // Skip to the first tag.
     while (xml_parser_.next() != ResXMLParser::START_TAG) {
@@ -65,15 +65,50 @@
   ResXMLTree xml_parser_;
 };
 
+TEST(AttributeResolutionLibraryTest, ApplyStyleWithDefaultStyleResId) {
+  AssetManager2 assetmanager;
+  auto apk_assets = ApkAssets::LoadAsSharedLibrary(GetTestDataPath() + "/styles/styles.apk");
+  ASSERT_NE(nullptr, apk_assets);
+  assetmanager.SetApkAssets({apk_assets.get()});
+
+  std::unique_ptr<Theme> theme = assetmanager.NewTheme();
+
+  std::array<uint32_t, 2> attrs{
+      {fix_package_id(R::attr::attr_one, 0x02), fix_package_id(R::attr::attr_two, 0x02)}};
+  std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
+  std::array<uint32_t, attrs.size() + 1> indices;
+  ApplyStyle(theme.get(), nullptr /*xml_parser*/, 0u /*def_style_attr*/,
+             fix_package_id(R::style::StyleOne, 0x02), attrs.data(), attrs.size(), values.data(),
+             indices.data());
+
+  const uint32_t public_flag = ResTable_typeSpec::SPEC_PUBLIC;
+
+  const uint32_t* values_cursor = values.data();
+  EXPECT_EQ(Res_value::TYPE_INT_DEC, values_cursor[STYLE_TYPE]);
+  EXPECT_EQ(1u, values_cursor[STYLE_DATA]);
+  EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
+  EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]);
+  EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
+  EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
+
+  values_cursor += STYLE_NUM_ENTRIES;
+  EXPECT_EQ(Res_value::TYPE_INT_DEC, values_cursor[STYLE_TYPE]);
+  EXPECT_EQ(2u, values_cursor[STYLE_DATA]);
+  EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
+  EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]);
+  EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
+  EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
+}
+
 TEST_F(AttributeResolutionTest, Theme) {
-  ResTable::Theme theme(table_);
-  ASSERT_EQ(NO_ERROR, theme.applyStyle(R::style::StyleTwo));
+  std::unique_ptr<Theme> theme = assetmanager_.NewTheme();
+  ASSERT_TRUE(theme->ApplyStyle(R::style::StyleTwo));
 
   std::array<uint32_t, 5> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
                                  R::attr::attr_four, R::attr::attr_empty}};
   std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
 
-  ASSERT_TRUE(ResolveAttrs(&theme, 0 /*def_style_attr*/, 0 /*def_style_res*/,
+  ASSERT_TRUE(ResolveAttrs(theme.get(), 0u /*def_style_attr*/, 0u /*def_style_res*/,
                            nullptr /*src_values*/, 0 /*src_values_length*/, attrs.data(),
                            attrs.size(), values.data(), nullptr /*out_indices*/));
 
@@ -126,8 +161,8 @@
                                  R::attr::attr_four, R::attr::attr_empty}};
   std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
 
-  ASSERT_TRUE(RetrieveAttributes(&table_, &xml_parser_, attrs.data(), attrs.size(), values.data(),
-                                 nullptr /*out_indices*/));
+  ASSERT_TRUE(RetrieveAttributes(&assetmanager_, &xml_parser_, attrs.data(), attrs.size(),
+                                 values.data(), nullptr /*out_indices*/));
 
   uint32_t* values_cursor = values.data();
   EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
@@ -171,15 +206,15 @@
 }
 
 TEST_F(AttributeResolutionXmlTest, ThemeAndXmlParser) {
-  ResTable::Theme theme(table_);
-  ASSERT_EQ(NO_ERROR, theme.applyStyle(R::style::StyleTwo));
+  std::unique_ptr<Theme> theme = assetmanager_.NewTheme();
+  ASSERT_TRUE(theme->ApplyStyle(R::style::StyleTwo));
 
   std::array<uint32_t, 6> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
                                  R::attr::attr_four, R::attr::attr_five, R::attr::attr_empty}};
   std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
   std::array<uint32_t, attrs.size() + 1> indices;
 
-  ApplyStyle(&theme, &xml_parser_, 0 /*def_style_attr*/, 0 /*def_style_res*/, attrs.data(),
+  ApplyStyle(theme.get(), &xml_parser_, 0u /*def_style_attr*/, 0u /*def_style_res*/, attrs.data(),
              attrs.size(), values.data(), indices.data());
 
   const uint32_t public_flag = ResTable_typeSpec::SPEC_PUBLIC;
diff --git a/libs/androidfw/tests/BenchmarkHelpers.cpp b/libs/androidfw/tests/BenchmarkHelpers.cpp
index 7149bee..faddfe5 100644
--- a/libs/androidfw/tests/BenchmarkHelpers.cpp
+++ b/libs/androidfw/tests/BenchmarkHelpers.cpp
@@ -33,19 +33,21 @@
     }
   }
 
+  // Make sure to force creation of the ResTable first, or else the configuration doesn't get set.
+  const ResTable& table = assetmanager.getResources(true);
   if (config != nullptr) {
     assetmanager.setConfiguration(*config);
   }
 
-  const ResTable& table = assetmanager.getResources(true);
-
   Res_value value;
   ResTable_config selected_config;
   uint32_t flags;
+  uint32_t last_ref = 0u;
 
   while (state.KeepRunning()) {
-    table.getResource(resid, &value, false /*may_be_bag*/, 0u /*density*/, &flags,
-                      &selected_config);
+    ssize_t block = table.getResource(resid, &value, false /*may_be_bag*/, 0u /*density*/, &flags,
+                                      &selected_config);
+    table.resolveReference(&value, block, &last_ref, &flags, &selected_config);
   }
 }
 
@@ -72,10 +74,12 @@
   Res_value value;
   ResTable_config selected_config;
   uint32_t flags;
+  uint32_t last_id = 0u;
 
   while (state.KeepRunning()) {
-    assetmanager.GetResource(resid, false /* may_be_bag */, 0u /* density_override */, &value,
-                             &selected_config, &flags);
+    ApkAssetsCookie cookie = assetmanager.GetResource(
+        resid, false /* may_be_bag */, 0u /* density_override */, &value, &selected_config, &flags);
+    assetmanager.ResolveReference(cookie, &value, &selected_config, &flags, &last_id);
   }
 }
 
diff --git a/libs/androidfw/tests/LoadedArsc_test.cpp b/libs/androidfw/tests/LoadedArsc_test.cpp
index 37ddafb..cae632d 100644
--- a/libs/androidfw/tests/LoadedArsc_test.cpp
+++ b/libs/androidfw/tests/LoadedArsc_test.cpp
@@ -16,6 +16,9 @@
 
 #include "androidfw/LoadedArsc.h"
 
+#include "android-base/file.h"
+#include "androidfw/ResourceUtils.h"
+
 #include "TestHelpers.h"
 #include "data/basic/R.h"
 #include "data/libclient/R.h"
@@ -27,6 +30,14 @@
 namespace libclient = com::android::libclient;
 namespace sparse = com::android::sparse;
 
+using ::android::base::ReadFileToString;
+using ::testing::Eq;
+using ::testing::Ge;
+using ::testing::IsNull;
+using ::testing::NotNull;
+using ::testing::SizeIs;
+using ::testing::StrEq;
+
 namespace android {
 
 TEST(LoadedArscTest, LoadSinglePackageArsc) {
@@ -35,39 +46,24 @@
                                       &contents));
 
   std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
-  ASSERT_NE(nullptr, loaded_arsc);
+  ASSERT_THAT(loaded_arsc, NotNull());
 
-  const std::vector<std::unique_ptr<const LoadedPackage>>& packages = loaded_arsc->GetPackages();
-  ASSERT_EQ(1u, packages.size());
-  EXPECT_EQ(std::string("com.android.app"), packages[0]->GetPackageName());
-  EXPECT_EQ(0x7f, packages[0]->GetPackageId());
+  const LoadedPackage* package =
+      loaded_arsc->GetPackageById(get_package_id(app::R::string::string_one));
+  ASSERT_THAT(package, NotNull());
+  EXPECT_THAT(package->GetPackageName(), StrEq("com.android.app"));
+  EXPECT_THAT(package->GetPackageId(), Eq(0x7f));
 
-  ResTable_config config;
-  memset(&config, 0, sizeof(config));
-  config.sdkVersion = 24;
+  const uint8_t type_index = get_type_id(app::R::string::string_one) - 1;
+  const uint16_t entry_index = get_entry_id(app::R::string::string_one);
 
-  FindEntryResult entry;
+  const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index);
+  ASSERT_THAT(type_spec, NotNull());
+  ASSERT_THAT(type_spec->type_count, Ge(1u));
 
-  ASSERT_TRUE(loaded_arsc->FindEntry(app::R::string::string_one, config, &entry));
-  ASSERT_NE(nullptr, entry.entry);
-}
-
-TEST(LoadedArscTest, FindDefaultEntry) {
-  std::string contents;
-  ASSERT_TRUE(
-      ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk", "resources.arsc", &contents));
-
-  std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
-  ASSERT_NE(nullptr, loaded_arsc);
-
-  ResTable_config desired_config;
-  memset(&desired_config, 0, sizeof(desired_config));
-  desired_config.language[0] = 'd';
-  desired_config.language[1] = 'e';
-
-  FindEntryResult entry;
-  ASSERT_TRUE(loaded_arsc->FindEntry(basic::R::string::test1, desired_config, &entry));
-  ASSERT_NE(nullptr, entry.entry);
+  const ResTable_type* type = type_spec->types[0];
+  ASSERT_THAT(type, NotNull());
+  ASSERT_THAT(LoadedPackage::GetEntry(type, entry_index), NotNull());
 }
 
 TEST(LoadedArscTest, LoadSparseEntryApp) {
@@ -76,15 +72,22 @@
                                       &contents));
 
   std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
-  ASSERT_NE(nullptr, loaded_arsc);
+  ASSERT_THAT(loaded_arsc, NotNull());
 
-  ResTable_config config;
-  memset(&config, 0, sizeof(config));
-  config.sdkVersion = 26;
+  const LoadedPackage* package =
+      loaded_arsc->GetPackageById(get_package_id(sparse::R::integer::foo_9));
+  ASSERT_THAT(package, NotNull());
 
-  FindEntryResult entry;
-  ASSERT_TRUE(loaded_arsc->FindEntry(sparse::R::integer::foo_9, config, &entry));
-  ASSERT_NE(nullptr, entry.entry);
+  const uint8_t type_index = get_type_id(sparse::R::integer::foo_9) - 1;
+  const uint16_t entry_index = get_entry_id(sparse::R::integer::foo_9);
+
+  const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index);
+  ASSERT_THAT(type_spec, NotNull());
+  ASSERT_THAT(type_spec->type_count, Ge(1u));
+
+  const ResTable_type* type = type_spec->types[0];
+  ASSERT_THAT(type, NotNull());
+  ASSERT_THAT(LoadedPackage::GetEntry(type, entry_index), NotNull());
 }
 
 TEST(LoadedArscTest, LoadSharedLibrary) {
@@ -93,14 +96,13 @@
                                       &contents));
 
   std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
-  ASSERT_NE(nullptr, loaded_arsc);
+  ASSERT_THAT(loaded_arsc, NotNull());
 
   const auto& packages = loaded_arsc->GetPackages();
-  ASSERT_EQ(1u, packages.size());
-
+  ASSERT_THAT(packages, SizeIs(1u));
   EXPECT_TRUE(packages[0]->IsDynamic());
-  EXPECT_EQ(std::string("com.android.lib_one"), packages[0]->GetPackageName());
-  EXPECT_EQ(0, packages[0]->GetPackageId());
+  EXPECT_THAT(packages[0]->GetPackageName(), StrEq("com.android.lib_one"));
+  EXPECT_THAT(packages[0]->GetPackageId(), Eq(0));
 
   const auto& dynamic_pkg_map = packages[0]->GetDynamicPackageMap();
 
@@ -114,25 +116,23 @@
                                       "resources.arsc", &contents));
 
   std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
-  ASSERT_NE(nullptr, loaded_arsc);
+  ASSERT_THAT(loaded_arsc, NotNull());
 
   const auto& packages = loaded_arsc->GetPackages();
-  ASSERT_EQ(1u, packages.size());
-
+  ASSERT_THAT(packages, SizeIs(1u));
   EXPECT_FALSE(packages[0]->IsDynamic());
-  EXPECT_EQ(std::string("com.android.libclient"), packages[0]->GetPackageName());
-  EXPECT_EQ(0x7f, packages[0]->GetPackageId());
+  EXPECT_THAT(packages[0]->GetPackageName(), StrEq("com.android.libclient"));
+  EXPECT_THAT(packages[0]->GetPackageId(), Eq(0x7f));
 
   const auto& dynamic_pkg_map = packages[0]->GetDynamicPackageMap();
 
   // The library has two dependencies.
-  ASSERT_EQ(2u, dynamic_pkg_map.size());
+  ASSERT_THAT(dynamic_pkg_map, SizeIs(2u));
+  EXPECT_THAT(dynamic_pkg_map[0].package_name, StrEq("com.android.lib_one"));
+  EXPECT_THAT(dynamic_pkg_map[0].package_id, Eq(0x02));
 
-  EXPECT_EQ(std::string("com.android.lib_one"), dynamic_pkg_map[0].package_name);
-  EXPECT_EQ(0x02, dynamic_pkg_map[0].package_id);
-
-  EXPECT_EQ(std::string("com.android.lib_two"), dynamic_pkg_map[1].package_name);
-  EXPECT_EQ(0x03, dynamic_pkg_map[1].package_id);
+  EXPECT_THAT(dynamic_pkg_map[1].package_name, StrEq("com.android.lib_two"));
+  EXPECT_THAT(dynamic_pkg_map[1].package_id, Eq(0x03));
 }
 
 TEST(LoadedArscTest, LoadAppAsSharedLibrary) {
@@ -143,13 +143,12 @@
   std::unique_ptr<const LoadedArsc> loaded_arsc =
       LoadedArsc::Load(StringPiece(contents), nullptr /*loaded_idmap*/, false /*system*/,
                        true /*load_as_shared_library*/);
-  ASSERT_NE(nullptr, loaded_arsc);
+  ASSERT_THAT(loaded_arsc, NotNull());
 
   const auto& packages = loaded_arsc->GetPackages();
-  ASSERT_EQ(1u, packages.size());
-
+  ASSERT_THAT(packages, SizeIs(1u));
   EXPECT_TRUE(packages[0]->IsDynamic());
-  EXPECT_EQ(0x7f, packages[0]->GetPackageId());
+  EXPECT_THAT(packages[0]->GetPackageId(), Eq(0x7f));
 }
 
 TEST(LoadedArscTest, LoadFeatureSplit) {
@@ -157,21 +156,67 @@
   ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/feature/feature.apk", "resources.arsc",
                                       &contents));
   std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
-  ASSERT_NE(nullptr, loaded_arsc);
+  ASSERT_THAT(loaded_arsc, NotNull());
 
-  ResTable_config desired_config;
-  memset(&desired_config, 0, sizeof(desired_config));
+  const LoadedPackage* package =
+      loaded_arsc->GetPackageById(get_package_id(basic::R::string::test3));
+  ASSERT_THAT(package, NotNull());
 
-  FindEntryResult entry;
-  ASSERT_TRUE(loaded_arsc->FindEntry(basic::R::string::test3, desired_config, &entry));
+  uint8_t type_index = get_type_id(basic::R::string::test3) - 1;
+  uint8_t entry_index = get_entry_id(basic::R::string::test3);
+
+  const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index);
+  ASSERT_THAT(type_spec, NotNull());
+  ASSERT_THAT(type_spec->type_count, Ge(1u));
+  ASSERT_THAT(type_spec->types[0], NotNull());
 
   size_t len;
-  const char16_t* type_name16 = entry.type_string_ref.string16(&len);
-  ASSERT_NE(nullptr, type_name16);
-  ASSERT_NE(0u, len);
+  const char16_t* type_name16 =
+      package->GetTypeStringPool()->stringAt(type_spec->type_spec->id - 1, &len);
+  ASSERT_THAT(type_name16, NotNull());
+  EXPECT_THAT(util::Utf16ToUtf8(StringPiece16(type_name16, len)), StrEq("string"));
 
-  std::string type_name = util::Utf16ToUtf8(StringPiece16(type_name16, len));
-  EXPECT_EQ(std::string("string"), type_name);
+  ASSERT_THAT(LoadedPackage::GetEntry(type_spec->types[0], entry_index), NotNull());
+}
+
+// AAPT(2) generates resource tables with chunks in a certain order. The rule is that
+// a RES_TABLE_TYPE_TYPE with id `i` must always be preceded by a RES_TABLE_TYPE_SPEC_TYPE with
+// id `i`. The RES_TABLE_TYPE_SPEC_TYPE does not need to be directly preceding, however.
+//
+// AAPT(2) generates something like:
+//   RES_TABLE_TYPE_SPEC_TYPE id=1
+//   RES_TABLE_TYPE_TYPE id=1
+//   RES_TABLE_TYPE_SPEC_TYPE id=2
+//   RES_TABLE_TYPE_TYPE id=2
+//
+// But the following is valid too:
+//   RES_TABLE_TYPE_SPEC_TYPE id=1
+//   RES_TABLE_TYPE_SPEC_TYPE id=2
+//   RES_TABLE_TYPE_TYPE id=1
+//   RES_TABLE_TYPE_TYPE id=2
+//
+TEST(LoadedArscTest, LoadOutOfOrderTypeSpecs) {
+  std::string contents;
+  ASSERT_TRUE(
+      ReadFileFromZipToString(GetTestDataPath() + "/out_of_order_types/out_of_order_types.apk",
+                              "resources.arsc", &contents));
+
+  std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
+  ASSERT_THAT(loaded_arsc, NotNull());
+
+  ASSERT_THAT(loaded_arsc->GetPackages(), SizeIs(1u));
+  const auto& package = loaded_arsc->GetPackages()[0];
+  ASSERT_THAT(package, NotNull());
+
+  const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(0);
+  ASSERT_THAT(type_spec, NotNull());
+  ASSERT_THAT(type_spec->type_count, Ge(1u));
+  ASSERT_THAT(type_spec->types[0], NotNull());
+
+  type_spec = package->GetTypeSpecByTypeIndex(1);
+  ASSERT_THAT(type_spec, NotNull());
+  ASSERT_THAT(type_spec->type_count, Ge(1u));
+  ASSERT_THAT(type_spec->types[0], NotNull());
 }
 
 class MockLoadedIdmap : public LoadedIdmap {
@@ -199,23 +244,33 @@
 };
 
 TEST(LoadedArscTest, LoadOverlay) {
-  std::string contents, overlay_contents;
-  ASSERT_TRUE(
-      ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk", "resources.arsc", &contents));
+  std::string contents;
   ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/overlay/overlay.apk", "resources.arsc",
-                                      &overlay_contents));
+                                      &contents));
 
   MockLoadedIdmap loaded_idmap;
 
   std::unique_ptr<const LoadedArsc> loaded_arsc =
-      LoadedArsc::Load(StringPiece(overlay_contents), &loaded_idmap);
-  ASSERT_NE(nullptr, loaded_arsc);
+      LoadedArsc::Load(StringPiece(contents), &loaded_idmap);
+  ASSERT_THAT(loaded_arsc, NotNull());
 
-  ResTable_config desired_config;
-  memset(&desired_config, 0, sizeof(desired_config));
+  const LoadedPackage* package = loaded_arsc->GetPackageById(0x08u);
+  ASSERT_THAT(package, NotNull());
 
-  FindEntryResult entry;
-  ASSERT_TRUE(loaded_arsc->FindEntry(0x08030001u, desired_config, &entry));
+  const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(0x03u - 1);
+  ASSERT_THAT(type_spec, NotNull());
+  ASSERT_THAT(type_spec->type_count, Ge(1u));
+  ASSERT_THAT(type_spec->types[0], NotNull());
+
+  // The entry being overlaid doesn't exist at the original entry index.
+  ASSERT_THAT(LoadedPackage::GetEntry(type_spec->types[0], 0x0001u), IsNull());
+
+  // Since this is an overlay, the actual entry ID must be mapped.
+  ASSERT_THAT(type_spec->idmap_entries, NotNull());
+  uint16_t target_entry_id = 0u;
+  ASSERT_TRUE(LoadedIdmap::Lookup(type_spec->idmap_entries, 0x0001u, &target_entry_id));
+  ASSERT_THAT(target_entry_id, Eq(0x0u));
+  ASSERT_THAT(LoadedPackage::GetEntry(type_spec->types[0], 0x0000), NotNull());
 }
 
 // structs with size fields (like Res_value, ResTable_entry) should be
diff --git a/libs/androidfw/tests/TestHelpers.h b/libs/androidfw/tests/TestHelpers.h
index 43a9955..df0c642 100644
--- a/libs/androidfw/tests/TestHelpers.h
+++ b/libs/androidfw/tests/TestHelpers.h
@@ -20,6 +20,7 @@
 #include <string>
 
 #include "androidfw/ResourceTypes.h"
+#include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
 #include "CommonHelpers.h"
diff --git a/libs/androidfw/tests/data/app/app.apk b/libs/androidfw/tests/data/app/app.apk
index ccb0824..c8ad86d 100644
--- a/libs/androidfw/tests/data/app/app.apk
+++ b/libs/androidfw/tests/data/app/app.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/app/assets/app_file.txt b/libs/androidfw/tests/data/app/assets/app_file.txt
new file mode 100644
index 0000000..b214e06
--- /dev/null
+++ b/libs/androidfw/tests/data/app/assets/app_file.txt
@@ -0,0 +1 @@
+app file
diff --git a/libs/androidfw/tests/data/app/assets/file.txt b/libs/androidfw/tests/data/app/assets/file.txt
new file mode 100644
index 0000000..0811542
--- /dev/null
+++ b/libs/androidfw/tests/data/app/assets/file.txt
@@ -0,0 +1 @@
+app override file
diff --git a/libs/androidfw/tests/data/app/build b/libs/androidfw/tests/data/app/build
index d418158..09af842 100755
--- a/libs/androidfw/tests/data/app/build
+++ b/libs/androidfw/tests/data/app/build
@@ -17,4 +17,11 @@
 
 set -e
 
-aapt package -I ../system/system.apk -M AndroidManifest.xml -S res -F app.apk -f
+aapt2 compile --dir res -o compiled.flata
+aapt2 link \
+    --manifest AndroidManifest.xml \
+    -I ../system/system.apk \
+    -A assets \
+    -o app.apk \
+    compiled.flata
+rm compiled.flata
diff --git a/libs/androidfw/tests/data/basic/R.h b/libs/androidfw/tests/data/basic/R.h
index 94a2a14..b7e814f 100644
--- a/libs/androidfw/tests/data/basic/R.h
+++ b/libs/androidfw/tests/data/basic/R.h
@@ -34,6 +34,7 @@
   struct layout {
     enum : uint32_t {
       main = 0x7f020000,
+      layoutt = 0x7f020001,
     };
   };
 
@@ -55,6 +56,7 @@
       number2 = 0x7f040001,
       ref1 = 0x7f040002,
       ref2 = 0x7f040003,
+      deep_ref = 0x7f040004,
 
       // From feature
       number3 = 0x80030000,
diff --git a/libs/androidfw/tests/data/basic/basic.apk b/libs/androidfw/tests/data/basic/basic.apk
index 18ef75e..1733b6a 100644
--- a/libs/androidfw/tests/data/basic/basic.apk
+++ b/libs/androidfw/tests/data/basic/basic.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/basic/res/layout/layout.xml b/libs/androidfw/tests/data/basic/res/layout/layout.xml
new file mode 100644
index 0000000..045ede4
--- /dev/null
+++ b/libs/androidfw/tests/data/basic/res/layout/layout.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<Button xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/ok"
+    android:layout_width="0sp"
+    android:layout_height="fill_parent"
+    android:layout_weight="1"
+    android:layout_marginStart="2dip"
+    android:layout_marginEnd="2dip"
+    android:textAppearance="?android:attr/textAppearanceMedium"
+    android:textStyle="bold"
+    android:text="@android:string/ok" />
\ No newline at end of file
diff --git a/libs/androidfw/tests/data/basic/res/values/values.xml b/libs/androidfw/tests/data/basic/res/values/values.xml
index 6c47459..b343562 100644
--- a/libs/androidfw/tests/data/basic/res/values/values.xml
+++ b/libs/androidfw/tests/data/basic/res/values/values.xml
@@ -22,6 +22,7 @@
     <attr name="attr2" format="reference|integer" />
 
     <public type="layout" name="main" id="0x7f020000" />
+    <public type="layout" name="layout" id="0x7f020001" />
 
     <public type="string" name="test1" id="0x7f030000" />
     <string name="test1">test1</string>
@@ -43,6 +44,18 @@
     <public type="integer" name="ref2" id="0x7f040003" />
     <integer name="ref2">12000</integer>
 
+    <public type="integer" name="deep_ref" id="0x7f040004" />
+    <integer name="deep_ref">@integer/deep_ref_1</integer>
+    <integer name="deep_ref_1">@integer/deep_ref_2</integer>
+    <integer name="deep_ref_2">@integer/deep_ref_3</integer>
+    <integer name="deep_ref_3">@integer/deep_ref_4</integer>
+    <integer name="deep_ref_4">@integer/deep_ref_5</integer>
+    <integer name="deep_ref_5">@integer/deep_ref_6</integer>
+    <integer name="deep_ref_6">@integer/deep_ref_7</integer>
+    <integer name="deep_ref_7">@integer/deep_ref_8</integer>
+    <integer name="deep_ref_8">@integer/deep_ref_9</integer>
+    <integer name="deep_ref_9">100</integer>
+
     <public type="style" name="Theme1" id="0x7f050000" />
     <style name="Theme1">
         <item name="com.android.basic:attr1">100</item>
diff --git a/libs/androidfw/tests/data/out_of_order_types/AndroidManifest.xml b/libs/androidfw/tests/data/out_of_order_types/AndroidManifest.xml
new file mode 100644
index 0000000..34016db
--- /dev/null
+++ b/libs/androidfw/tests/data/out_of_order_types/AndroidManifest.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.app" />
diff --git a/libs/androidfw/tests/data/out_of_order_types/build b/libs/androidfw/tests/data/out_of_order_types/build
new file mode 100755
index 0000000..8496f81
--- /dev/null
+++ b/libs/androidfw/tests/data/out_of_order_types/build
@@ -0,0 +1,22 @@
+#!/bin/bash
+#
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+set -e
+
+aapt2 compile --dir res -o compiled.flata
+aapt2 link --manifest AndroidManifest.xml -o out_of_order_types.apk compiled.flata
+rm compiled.flata
diff --git a/libs/androidfw/tests/data/out_of_order_types/edited_resources.arsc.txt b/libs/androidfw/tests/data/out_of_order_types/edited_resources.arsc.txt
new file mode 100644
index 0000000..eca8f47
--- /dev/null
+++ b/libs/androidfw/tests/data/out_of_order_types/edited_resources.arsc.txt
@@ -0,0 +1,43 @@
+00000000: 0200 0c00 ac02 0000 0100 0000 0100 1c00  ................
+00000010: 1c00 0000 0000 0000 0000 0000 0001 0000  ................
+00000020: 1c00 0000 0000 0000 0002 2001 8402 0000  .......... .....
+00000030: 7f00 0000 6300 6f00 6d00 2e00 6100 6e00  ....c.o.m...a.n.
+00000040: 6400 7200 6f00 6900 6400 2e00 6100 7000  d.r.o.i.d...a.p.
+00000050: 7000 0000 0000 0000 0000 0000 0000 0000  p...............
+00000060: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+00000070: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+00000080: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+00000090: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+000000a0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+000000b0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+000000c0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+000000d0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+000000e0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+000000f0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+00000100: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+00000110: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+00000120: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+00000130: 0000 0000 2001 0000 0000 0000 6401 0000  .... .......d...
+00000140: 0000 0000 0000 0000 0100 1c00 4400 0000  ............D...
+00000150: 0200 0000 0000 0000 0000 0000 2400 0000  ............$...
+00000160: 0000 0000 0000 0000 0c00 0000 0400 6200  ..............b.
+00000170: 6f00 6f00 6c00 0000 0700 6900 6e00 7400  o.o.l.....i.n.t.
+00000180: 6500 6700 6500 7200 0000 0000 0100 1c00  e.g.e.r.........
+00000190: 2800 0000 0100 0000 0000 0000 0001 0000  (...............
+000001a0: 2000 0000 0000 0000 0000 0000 0404 7465   .............te
+000001b0: 7374 0000 0202 1000 1400 0000 0100 0000  st..............
+000001c0: 0100 0000 0000 0000 0202 1000 1400 0000
+000001d0: 0200 0000 0100 0000 0000 0000 0102 5400
+000001e0: 6800 0000 0100 0000 0100 0000 5800 0000
+000001f0: 4000 0000 0000 0000 0000 0000 0000 0000
+00000200: 0000 0000 0000 0000 0000 0000 0000 0000
+00000210: 0000 0000 0000 0000 0000 0000 0000 0000
+00000220: 0000 0000 0000 0000 0000 0000 0000 0000
+00000230: 0000 0000 0800 0000 0000 0000 0800 0012
+00000240: ffff ffff 0102 5400 6800 0000 0200 0000  ......T.h.......
+00000250: 0100 0000 5800 0000 4000 0000 0000 0000  ....X...@.......
+00000260: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+00000270: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+00000280: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+00000290: 0000 0000 0000 0000 0000 0000 0800 0000  ................
+000002a0: 0000 0000 0800 0010 0100 0000            ............
diff --git a/libs/androidfw/tests/data/out_of_order_types/out_of_order_types.apk b/libs/androidfw/tests/data/out_of_order_types/out_of_order_types.apk
new file mode 100644
index 0000000..75146e0
--- /dev/null
+++ b/libs/androidfw/tests/data/out_of_order_types/out_of_order_types.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/out_of_order_types/res/values/values.xml b/libs/androidfw/tests/data/out_of_order_types/res/values/values.xml
new file mode 100644
index 0000000..7c54fba
--- /dev/null
+++ b/libs/androidfw/tests/data/out_of_order_types/res/values/values.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <bool name="test">true</bool>
+    <integer name="test">1</integer>
+</resources>
diff --git a/libs/androidfw/tests/data/system/assets/file.txt b/libs/androidfw/tests/data/system/assets/file.txt
new file mode 100644
index 0000000..f73f309
--- /dev/null
+++ b/libs/androidfw/tests/data/system/assets/file.txt
@@ -0,0 +1 @@
+file
diff --git a/libs/androidfw/tests/data/system/assets/subdir/subdir_file.txt b/libs/androidfw/tests/data/system/assets/subdir/subdir_file.txt
new file mode 100644
index 0000000..3f74eb6
--- /dev/null
+++ b/libs/androidfw/tests/data/system/assets/subdir/subdir_file.txt
@@ -0,0 +1 @@
+subdir file
diff --git a/libs/androidfw/tests/data/system/build b/libs/androidfw/tests/data/system/build
index bfbdf4c..b65145a 100755
--- a/libs/androidfw/tests/data/system/build
+++ b/libs/androidfw/tests/data/system/build
@@ -17,4 +17,6 @@
 
 set -e
 
-aapt package -x -M AndroidManifest.xml -S res -F system.apk -f
+aapt2 compile --dir res -o compiled.flata
+aapt2 link --manifest AndroidManifest.xml -A assets -o system.apk compiled.flata
+rm compiled.flata
diff --git a/libs/androidfw/tests/data/system/res/values-sv/values.xml b/libs/androidfw/tests/data/system/res/values-sv/values.xml
index b97bdb6..5f60d21 100644
--- a/libs/androidfw/tests/data/system/res/values-sv/values.xml
+++ b/libs/androidfw/tests/data/system/res/values-sv/values.xml
@@ -15,6 +15,5 @@
 -->
 
 <resources>
-    <public type="integer" name="number" id="0x01030000" />
     <integer name="number">1</integer>
 </resources>
diff --git a/libs/androidfw/tests/data/system/res/values/themes.xml b/libs/androidfw/tests/data/system/res/values/themes.xml
index 35d43c7..7893c94 100644
--- a/libs/androidfw/tests/data/system/res/values/themes.xml
+++ b/libs/androidfw/tests/data/system/res/values/themes.xml
@@ -18,6 +18,7 @@
     <public name="background" type="attr" id="0x01010000"/>
     <public name="foreground" type="attr" id="0x01010001"/>
     <public name="Theme.One" type="style" id="0x01020000"/>
+    <public type="integer" name="number" id="0x01030000" />
 
     <attr name="background" format="color|reference"/>
     <attr name="foreground" format="color|reference"/>
diff --git a/libs/androidfw/tests/data/system/system.apk b/libs/androidfw/tests/data/system/system.apk
index 1299016..9045d6c 100644
--- a/libs/androidfw/tests/data/system/system.apk
+++ b/libs/androidfw/tests/data/system/system.apk
Binary files differ
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 7d2ad91..2dd8c36 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -1246,7 +1246,6 @@
      *
      * @param enabled true to enable location. false to disable location
      * @param userHandle the user to set
-     * @return true if the value was set, false on database errors
      *
      * @hide
      */
diff --git a/media/java/android/media/MediaBrowser2.java b/media/java/android/media/MediaBrowser2.java
index dea38a8..35edc4a 100644
--- a/media/java/android/media/MediaBrowser2.java
+++ b/media/java/android/media/MediaBrowser2.java
@@ -46,12 +46,13 @@
          * {@code rootMediaId} and {@code rootExtra} can be {@code null} if the library root isn't
          * available.
          *
+         * @param browser the browser for this event
          * @param rootHints rootHints that you previously requested.
          * @param rootMediaId media id of the library root. Can be {@code null}
          * @param rootExtra extra of the library root. Can be {@code null}
          */
-        public void onGetLibraryRootDone(Bundle rootHints, @Nullable String rootMediaId,
-                @Nullable Bundle rootExtra) { }
+        public void onGetLibraryRootDone(@NonNull MediaBrowser2 browser, @Nullable Bundle rootHints,
+                @Nullable String rootMediaId, @Nullable Bundle rootExtra) { }
 
         /**
          * Called when there's change in the parent's children.
@@ -60,18 +61,20 @@
          * {@link MediaLibrarySession#notifyChildrenChanged(ControllerInfo, String, int, Bundle)} or
          * {@link MediaLibrarySession#notifyChildrenChanged(String, int, Bundle)} for the parent.
          *
+         * @param browser the browser for this event
          * @param parentId parent id that you've specified with {@link #subscribe(String, Bundle)}
          * @param itemCount number of children
          * @param extras extra bundle from the library service. Can be differ from extras that
          *               you've specified with {@link #subscribe(String, Bundle)}.
          */
-        public void onChildrenChanged(@NonNull String parentId, int itemCount,
-                @Nullable Bundle extras) { }
+        public void onChildrenChanged(@NonNull MediaBrowser2 browser, @NonNull String parentId,
+                int itemCount, @Nullable Bundle extras) { }
 
         /**
          * Called when the list of items has been returned by the library service for the previous
          * {@link MediaBrowser2#getChildren(String, int, int, Bundle)}.
          *
+         * @param browser the browser for this event
          * @param parentId parent id
          * @param page page number that you've specified with
          *             {@link #getChildren(String, int, int, Bundle)}
@@ -80,8 +83,9 @@
          * @param result result. Can be {@code null}
          * @param extras extra bundle from the library service
          */
-        public void onGetChildrenDone(@NonNull String parentId, int page, int pageSize,
-                @Nullable List<MediaItem2> result, @Nullable Bundle extras) { }
+        public void onGetChildrenDone(@NonNull MediaBrowser2 browser, @NonNull String parentId,
+                int page, int pageSize, @Nullable List<MediaItem2> result,
+                @Nullable Bundle extras) { }
 
         /**
          * Called when the item has been returned by the library service for the previous
@@ -89,21 +93,24 @@
          * <p>
          * Result can be null if there had been error.
          *
+         * @param browser the browser for this event
          * @param mediaId media id
          * @param result result. Can be {@code null}
          */
-        public void onGetItemDone(@NonNull String mediaId, @Nullable MediaItem2 result) { }
+        public void onGetItemDone(@NonNull MediaBrowser2 browser, @NonNull String mediaId,
+                @Nullable MediaItem2 result) { }
 
         /**
          * Called when there's change in the search result requested by the previous
          * {@link MediaBrowser2#search(String, Bundle)}.
          *
+         * @param browser the browser for this event
          * @param query search query that you've specified with {@link #search(String, Bundle)}
          * @param itemCount The item count for the search result
          * @param extras extra bundle from the library service
          */
-        public void onSearchResultChanged(@NonNull String query, int itemCount,
-                @Nullable Bundle extras) { }
+        public void onSearchResultChanged(@NonNull MediaBrowser2 browser, @NonNull String query,
+                int itemCount, @Nullable Bundle extras) { }
 
         /**
          * Called when the search result has been returned by the library service for the previous
@@ -111,6 +118,7 @@
          * <p>
          * Result can be null if there had been error.
          *
+         * @param browser the browser for this event
          * @param query search query that you've specified with
          *              {@link #getSearchResult(String, int, int, Bundle)}
          * @param page page number that you've specified with
@@ -120,8 +128,9 @@
          * @param result result. Can be {@code null}.
          * @param extras extra bundle from the library service
          */
-        public void onGetSearchResultDone(@NonNull String query, int page, int pageSize,
-                @Nullable List<MediaItem2> result, @Nullable Bundle extras) { }
+        public void onGetSearchResultDone(@NonNull MediaBrowser2 browser, @NonNull String query,
+                int page, int pageSize, @Nullable List<MediaItem2> result,
+                @Nullable Bundle extras) { }
     }
 
     public MediaBrowser2(@NonNull Context context, @NonNull SessionToken2 token,
@@ -139,10 +148,10 @@
 
     /**
      * Get the library root. Result would be sent back asynchronously with the
-     * {@link BrowserCallback#onGetLibraryRootDone(Bundle, String, Bundle)}.
+     * {@link BrowserCallback#onGetLibraryRootDone(MediaBrowser2, Bundle, String, Bundle)}.
      *
      * @param rootHints hint for the root
-     * @see BrowserCallback#onGetLibraryRootDone(Bundle, String, Bundle)
+     * @see BrowserCallback#onGetLibraryRootDone(MediaBrowser2, Bundle, String, Bundle)
      */
     public void getLibraryRoot(Bundle rootHints) {
         mProvider.getLibraryRoot_impl(rootHints);
@@ -150,9 +159,9 @@
 
     /**
      * Subscribe to a parent id for the change in its children. When there's a change,
-     * {@link BrowserCallback#onChildrenChanged(String, int, Bundle)} will be called with the bundle
-     * that you've specified. You should call {@link #getChildren(String, int, int, Bundle)} to get
-     * the actual contents for the parent.
+     * {@link BrowserCallback#onChildrenChanged(MediaBrowser2, String, int, Bundle)} will be called
+     * with the bundle that you've specified. You should call
+     * {@link #getChildren(String, int, int, Bundle)} to get the actual contents for the parent.
      *
      * @param parentId parent id
      * @param extras extra bundle
@@ -176,7 +185,7 @@
 
     /**
      * Get list of children under the parent. Result would be sent back asynchronously with the
-     * {@link BrowserCallback#onGetChildrenDone(String, int, int, List, Bundle)}.
+     * {@link BrowserCallback#onGetChildrenDone(MediaBrowser2, String, int, int, List, Bundle)}.
      *
      * @param parentId parent id for getting the children.
      * @param page page number to get the result. Starts from {@code 1}
@@ -189,7 +198,7 @@
 
     /**
      * Get the media item with the given media id. Result would be sent back asynchronously with the
-     * {@link BrowserCallback#onGetItemDone(String, MediaItem2)}.
+     * {@link BrowserCallback#onGetItemDone(MediaBrowser2, String, MediaItem2)}.
      *
      * @param mediaId media id for specifying the item
      */
@@ -199,8 +208,9 @@
 
     /**
      * Send a search request to the library service. When the search result is changed,
-     * {@link BrowserCallback#onSearchResultChanged(String, int, Bundle)} will be called. You should
-     * call {@link #getSearchResult(String, int, int, Bundle)} to get the actual search result.
+     * {@link BrowserCallback#onSearchResultChanged(MediaBrowser2, String, int, Bundle)} will be
+     * called. You should call {@link #getSearchResult(String, int, int, Bundle)} to get the actual
+     * search result.
      *
      * @param query search query. Should not be an empty string.
      * @param extras extra bundle
@@ -211,7 +221,8 @@
 
     /**
      * Get the search result from lhe library service. Result would be sent back asynchronously with
-     * the {@link BrowserCallback#onGetSearchResultDone(String, int, int, List, Bundle)}.
+     * the
+     * {@link BrowserCallback#onGetSearchResultDone(MediaBrowser2, String, int, int, List, Bundle)}.
      *
      * @param query search query that you've specified with {@link #search(String, Bundle)}
      * @param page page number to get search result. Starts from {@code 1}
diff --git a/media/java/android/media/MediaController2.java b/media/java/android/media/MediaController2.java
index 38d5000..da2b8e0 100644
--- a/media/java/android/media/MediaController2.java
+++ b/media/java/android/media/MediaController2.java
@@ -51,9 +51,9 @@
  * <p>
  * When controlling {@link MediaSessionService2}, the {@link MediaController2} would be
  * available only if the session service allows this controller by
- * {@link MediaSession2.SessionCallback#onConnect(ControllerInfo)} for the service. Wait
- * {@link ControllerCallback#onConnected(CommandGroup)} or
- * {@link ControllerCallback#onDisconnected()} for the result.
+ * {@link MediaSession2.SessionCallback#onConnect(MediaSession2, ControllerInfo)} for the service.
+ * Wait {@link ControllerCallback#onConnected(MediaController2, CommandGroup)} or
+ * {@link ControllerCallback#onDisconnected(MediaController2)} for the result.
  * <p>
  * A controller can be created through token from {@link MediaSessionManager} if you hold the
  * signature|privileged permission "android.permission.MEDIA_CONTENT_CONTROL" permission or are
@@ -75,9 +75,11 @@
          * Called when the controller is successfully connected to the session. The controller
          * becomes available afterwards.
          *
+         * @param controller the controller for this event
          * @param allowedCommands commands that's allowed by the session.
          */
-        public void onConnected(CommandGroup allowedCommands) { }
+        public void onConnected(@NonNull MediaController2 controller,
+                @NonNull CommandGroup allowedCommands) { }
 
         /**
          * Called when the session refuses the controller or the controller is disconnected from
@@ -86,113 +88,149 @@
          * <p>
          * It will be also called after the {@link #close()}, so you can put clean up code here.
          * You don't need to call {@link #close()} after this.
+         *
+         * @param controller the controller for this event
+         * @param controller controller for this event
          */
-        public void onDisconnected() { }
+        public void onDisconnected(@NonNull MediaController2 controller) { }
 
         /**
          * Called when the session set the custom layout through the
          * {@link MediaSession2#setCustomLayout(ControllerInfo, List)}.
          * <p>
-         * Can be called before {@link #onConnected(CommandGroup)} is called.
+         * Can be called before {@link #onConnected(MediaController2, CommandGroup)} is called.
          *
+         * @param controller the controller for this event
          * @param layout
          */
-        public void onCustomLayoutChanged(List<CommandButton> layout) { }
+        public void onCustomLayoutChanged(@NonNull MediaController2 controller,
+                @NonNull List<CommandButton> layout) { }
 
         /**
          * Called when the session has changed anything related with the {@link PlaybackInfo}.
          *
+         * @param controller the controller for this event
          * @param info new playback info
          */
-        public void onPlaybackInfoChanged(PlaybackInfo info) { }
+        public void onPlaybackInfoChanged(@NonNull MediaController2 controller,
+                @NonNull PlaybackInfo info) { }
 
         /**
          * Called when the allowed commands are changed by session.
          *
+         * @param controller the controller for this event
          * @param commands newly allowed commands
          */
-        public void onAllowedCommandsChanged(CommandGroup commands) { }
+        public void onAllowedCommandsChanged(@NonNull MediaController2 controller,
+                @NonNull CommandGroup commands) { }
 
         /**
          * Called when the session sent a custom command.
          *
+         * @param controller the controller for this event
          * @param command
          * @param args
          * @param receiver
          */
-        public void onCustomCommand(Command command, @Nullable Bundle args,
+        public void onCustomCommand(@NonNull MediaController2 controller,
+                @NonNull Command command, @Nullable Bundle args,
                 @Nullable ResultReceiver receiver) { }
 
         /**
          * Called when the playlist is changed.
          * <p>
-         * When it's called, you should invalidate previous playback information such as position,
-         * player state, current item, etc.
+         * If the previously playing media item is gone, you should invalidate previous playback
+         * information and wait for later callbacks.
          *
+         * @param controller the controller for this event
          * @param playlist A new playlist set by the session.
+         * @see #onPositionChanged(long, long)
+         * @see #onBufferedPositionChanged(long)
+         * @see #onCurrentPlaylistItemChanged(MediaItem2)
          */
-        // TODO(jaewan): Enhance doc
-        public void onPlaylistChanged(@NonNull List<MediaItem2> playlist) { }
+        public void onPlaylistChanged(@NonNull MediaController2 controller,
+                @NonNull List<MediaItem2> playlist) { }
 
         /**
          * Called when the playback state is changed.
          *
+         * @param controller the controller for this event
          * @param state latest playback state
          * @hide
          */
-        // TODo(jaewan): Remove
-        public void onPlaybackStateChanged(@NonNull PlaybackState2 state) { }
+        // TODO(jaewan): Remove (b/73971431)
+        public void onPlaybackStateChanged(@NonNull MediaController2 controller,
+                @NonNull PlaybackState2 state) { }
 
         /**
          * Called when the player state is changed.
          *
+         * @param controller the controller for this event
          * @param state
          */
-        public void onPlayerStateChanged(int state) { }
+        public void onPlayerStateChanged(@NonNull MediaController2 controller, int state) { }
 
         /**
          * Called when the player's position is changed
          *
-         * @param updateTimeMs timestamp when the position information is sent from the session
+         * @param controller the controller for this event
+         * @param eventTimeMs timestamp when the position information is sent from the session
          * @param positionMs position in millis
          */
-        public void onPositionChanged(long updateTimeMs, long positionMs) { }
+        public void onPositionChanged(@NonNull MediaController2 controller,
+                long eventTimeMs, long positionMs) { }
 
         /**
          * Called when playback speed is changed.
          *
+         * @param controller the controller for this event
          * @param speed speed
          */
-        public void onPlaybackSpeedChanged(float speed) { }
+        public void onPlaybackSpeedChanged(@NonNull MediaController2 controller,
+                float speed) { }
 
         /**
          * Called when the player's buffering position
          *
+         * @param controller the controller for this event
          * @param positionMs buffering position in millis
          */
-        public void onBufferedPositionChanged(long positionMs) { }
+        public void onBufferedPositionChanged(@NonNull MediaController2 controller,
+                long positionMs) { }
 
         /**
          * Called when a error from
          *
+         * @param controller the controller for this event
          * @param errorCode error code
          * @param extras extra information
          */
-        public void onError(@ErrorCode int errorCode, @Nullable Bundle extras) { }
+        public void onError(@NonNull MediaController2 controller, @ErrorCode int errorCode,
+                @Nullable Bundle extras) { }
 
         /**
          * Called when the player's current playing item is changed
+         * <p>
+         * When it's called, you should invalidate previous playback information and wait for later
+         * callbacks.
          *
+         * @param controller the controller for this event
          * @param item new item
+         * @see #onPositionChanged(long, long)
+         * @see #onBufferedPositionChanged(long)
+         * @see #onCurrentPlaylistItemChanged(MediaItem2)
          */
-        public void onCurrentPlaylistItemChanged(MediaItem2 item) { }
+        public void onCurrentPlaylistItemChanged(@NonNull MediaController2 controller,
+                @NonNull MediaItem2 item) { }
 
         /**
          * Called when the playlist parameters are changed.
          *
+         * @param controller the controller for this event
          * @param params The new play list parameters.
          */
-        public void onPlaylistParamsChanged(@NonNull PlaylistParams params) { }
+        public void onPlaylistParamsChanged(@NonNull MediaController2 controller,
+                @NonNull PlaylistParams params) { }
     }
 
     /**
@@ -295,7 +333,6 @@
      * @param executor executor to run callbacks on.
      * @param callback controller callback to receive changes in
      */
-    // TODO(jaewan): Put @CallbackExecutor to the constructor.
     public MediaController2(@NonNull Context context, @NonNull SessionToken2 token,
             @NonNull @CallbackExecutor Executor executor, @NonNull ControllerCallback callback) {
         super();
@@ -577,7 +614,7 @@
 
     /**
      * Get the lastly cached {@link PlaybackState2} from
-     * {@link ControllerCallback#onPlaybackStateChanged(PlaybackState2)}.
+     * {@link ControllerCallback#onPlaybackStateChanged(MediaController2, PlaybackState2)}.
      * <p>
      * It may return {@code null} before the first callback or session has sent {@code null}
      * playback state.
@@ -590,7 +627,8 @@
     }
 
     /**
-     * Get the lastly cached player state from {@link ControllerCallback#onPlayerStateChanged(int)}.
+     * Get the lastly cached player state from
+     * {@link ControllerCallback#onPlayerStateChanged(MediaController2, int)}.
      *
      * @return player state
      */
@@ -599,7 +637,8 @@
     }
 
     /**
-     * Get the lastly cached position from {@link ControllerCallback#onPositionChanged(long, long)}.
+     * Get the lastly cached position from
+     * {@link ControllerCallback#onPositionChanged(MediaController2, long, long)}.
      * <p>
      * This returns the calculated value of the position, based on the difference between the
      * update time and current time.
@@ -612,7 +651,7 @@
 
     /**
      * Get the lastly cached playback speed from
-     * {@link ControllerCallback#onPlaybackSpeedChanged(float)}.
+     * {@link ControllerCallback#onPlaybackSpeedChanged(MediaController2, float)}.
      *
      * @return speed
      */
@@ -624,12 +663,12 @@
      * Set the playback speed.
      */
     public void setPlaybackSpeed(float speed) {
-        // TODO: implement this
+        // TODO(jaewan): implement this (b/74093080)
     }
 
     /**
      * Get the lastly cached buffered position from
-     * {@link ControllerCallback#onBufferedPositionChanged(long)}.
+     * {@link ControllerCallback#onBufferedPositionChanged(MediaController2, long)}.
      *
      * @return buffering position in millis
      */
@@ -639,7 +678,7 @@
 
     /**
      * Get the lastly cached current item from
-     * {@link ControllerCallback#onCurrentPlaylistItemChanged(MediaItem2)}.
+     * {@link ControllerCallback#onCurrentPlaylistItemChanged(MediaController2, MediaItem2)}.
      *
      * @return index of the current item
      */
diff --git a/media/java/android/media/MediaItem2.java b/media/java/android/media/MediaItem2.java
index f9eceab..f6edd0c 100644
--- a/media/java/android/media/MediaItem2.java
+++ b/media/java/android/media/MediaItem2.java
@@ -70,7 +70,6 @@
      * @return a new bundle instance
      */
     public Bundle toBundle() {
-        // TODO(jaewan): Fill here when we rebase.
         return mProvider.toBundle_impl();
     }
 
diff --git a/media/java/android/media/MediaLibraryService2.java b/media/java/android/media/MediaLibraryService2.java
index 5917190..2372685 100644
--- a/media/java/android/media/MediaLibraryService2.java
+++ b/media/java/android/media/MediaLibraryService2.java
@@ -85,6 +85,7 @@
              * should return null if the client is not allowed to access this
              * information.
              *
+             * @param session the session for this event
              * @param controllerInfo information of the controller requesting access to browse media.
              * @param rootHints An optional bundle of service-specific arguments to send
              * to the media library service when connecting and retrieving the
@@ -95,8 +96,8 @@
              * @see LibraryRoot#EXTRA_OFFLINE
              * @see LibraryRoot#EXTRA_SUGGESTED
              */
-            public @Nullable LibraryRoot onGetLibraryRoot(@NonNull ControllerInfo controllerInfo,
-                    @Nullable Bundle rootHints) {
+            public @Nullable LibraryRoot onGetLibraryRoot(@NonNull MediaLibrarySession session,
+                    @NonNull ControllerInfo controllerInfo, @Nullable Bundle rootHints) {
                 return null;
             }
 
@@ -105,11 +106,12 @@
              * <p>
              * Return {@code null} for no result or error.
              *
+             * @param session the session for this event
              * @param mediaId item id to get media item.
              * @return a media item. {@code null} for no result or error.
              */
-            public @Nullable MediaItem2 onGetItem(@NonNull ControllerInfo controllerInfo,
-                    @NonNull String mediaId) {
+            public @Nullable MediaItem2 onGetItem(@NonNull MediaLibrarySession session,
+                    @NonNull ControllerInfo controllerInfo, @NonNull String mediaId) {
                 return null;
             }
 
@@ -118,14 +120,16 @@
              * <p>
              * Return an empty list for no children, and return {@code null} for the error.
              *
+             * @param session the session for this event
              * @param parentId parent id to get children
              * @param page number of page
              * @param pageSize size of the page
              * @param extras extra bundle
              * @return list of children. Can be {@code null}.
              */
-            public @Nullable List<MediaItem2> onGetChildren(@NonNull ControllerInfo controller,
-                    @NonNull String parentId, int page, int pageSize, @Nullable Bundle extras) {
+            public @Nullable List<MediaItem2> onGetChildren(@NonNull MediaLibrarySession session,
+                    @NonNull ControllerInfo controller, @NonNull String parentId, int page,
+                    int pageSize, @Nullable Bundle extras) {
                 return null;
             }
 
@@ -136,32 +140,37 @@
              * {@link MediaLibrarySession#notifyChildrenChanged(ControllerInfo, String, int, Bundle)}
              * when the parent is changed.
              *
+             * @param session the session for this event
              * @param controller controller
              * @param parentId parent id
              * @param extras extra bundle
              */
-            public void onSubscribe(@NonNull ControllerInfo controller, @NonNull String parentId,
+            public void onSubscribe(@NonNull MediaLibrarySession session,
+                    @NonNull ControllerInfo controller, @NonNull String parentId,
                     @Nullable Bundle extras) {
             }
 
             /**
              * Called when a controller unsubscribes to the parent.
              *
+             * @param session the session for this event
              * @param controller controller
              * @param parentId parent id
              */
-            public void onUnsubscribe(@NonNull ControllerInfo controller,
-                    @NonNull String parentId) {
+            public void onUnsubscribe(@NonNull MediaLibrarySession session,
+                    @NonNull ControllerInfo controller, @NonNull String parentId) {
             }
 
             /**
              * Called when a controller requests search.
              *
+             * @param session the session for this event
              * @param query The search query sent from the media browser. It contains keywords
              *              separated by space.
              * @param extras The bundle of service-specific arguments sent from the media browser.
              */
-            public void onSearch(@NonNull ControllerInfo controllerInfo, @NonNull String query,
+            public void onSearch(@NonNull MediaLibrarySession session,
+                    @NonNull ControllerInfo controllerInfo, @NonNull String query,
                     @Nullable Bundle extras) {
             }
 
@@ -171,17 +180,18 @@
              * <p>
              * Return an empty list for no search result, and return {@code null} for the error.
              *
+             * @param session the session for this event
              * @param controllerInfo Information of the controller requesting the search result.
              * @param query The search query which was previously sent through
-             *              {@link #onSearch(ControllerInfo, String, Bundle)} call.
+             *              {@link #onSearch(MediaLibrarySession, ControllerInfo, String, Bundle)}.
              * @param page page number. Starts from {@code 1}.
              * @param pageSize page size. Should be greater or equal to {@code 1}.
              * @param extras The bundle of service-specific arguments sent from the media browser.
              * @return search result. {@code null} for error.
              */
             public @Nullable List<MediaItem2> onGetSearchResult(
-                    @NonNull ControllerInfo controllerInfo, @NonNull String query, int page,
-                    int pageSize, @Nullable Bundle extras) {
+                    @NonNull MediaLibrarySession session, @NonNull ControllerInfo controllerInfo,
+                    @NonNull String query, int page, int pageSize, @Nullable Bundle extras) {
                 return null;
             }
         }
@@ -335,8 +345,8 @@
          * supplied as a root hint for retrieving media items that are recently played.
          * If the media library service can provide such media items, the implementation must return
          * the key in the root hint when
-         * {@link MediaLibrarySessionCallback#onGetLibraryRoot(ControllerInfo, Bundle)} is called
-         * back.
+         * {@link MediaLibrarySessionCallback#onGetLibraryRoot(MediaLibrarySession, ControllerInfo, Bundle)}
+         * is called back.
          *
          * <p>The root hint may contain multiple keys.
          *
@@ -354,8 +364,8 @@
          * internet connection.
          * If the media library service can provide such media items, the implementation must return
          * the key in the root hint when
-         * {@link MediaLibrarySessionCallback#onGetLibraryRoot(ControllerInfo, Bundle)} is called
-         * back.
+         * {@link MediaLibrarySessionCallback#onGetLibraryRoot(MediaLibrarySession, ControllerInfo, Bundle)}
+         * is called back.
          *
          * <p>The root hint may contain multiple keys.
          *
@@ -374,8 +384,8 @@
          * suggestion.
          * If the media library service can provide such media items, the implementation must return
          * the key in the root hint when
-         * {@link MediaLibrarySessionCallback#onGetLibraryRoot(ControllerInfo, Bundle)} is called
-         * back.
+         * {@link MediaLibrarySessionCallback#onGetLibraryRoot(MediaLibrarySession, ControllerInfo, Bundle)}
+         * is called back.
          *
          * <p>The root hint may contain multiple keys.
          *
diff --git a/media/java/android/media/MediaMetadata2.java b/media/java/android/media/MediaMetadata2.java
index 07367bb..502f929 100644
--- a/media/java/android/media/MediaMetadata2.java
+++ b/media/java/android/media/MediaMetadata2.java
@@ -37,7 +37,6 @@
 //   - Don't implement Parcelable for updatable support.
 //   - Also support MediaDescription features. MediaDescription is deprecated instead because
 //     it was insufficient for controller to display media contents.
-// TODO(jaewan): Add @see for APIs from MediaDescription
 public final class MediaMetadata2 {
     /**
      * The metadata key for a {@link CharSequence} or {@link String} typed value to retrieve the
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index e0047d6..0d472ab 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -1339,6 +1339,7 @@
      * this method, you will have to initialize it again by setting the
      * data source and calling prepare().
      */
+    @Override
     public abstract void reset();
 
     /**
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index 50bf738..50e3543 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -109,18 +109,21 @@
     private boolean mBypassInterruptionPolicy;
     private final CloseGuard mGuard = CloseGuard.get();
 
-    private final Object mPlLock = new Object();
+    private final Object mSrcLock = new Object();
+    //--- guarded by |mSrcLock| start
+    private long mSrcIdGenerator = 0;
     private DataSourceDesc mCurrentDSD;
-    private long mCurrentSrcId = 0;
-    private List<DataSourceDesc> mPlaylist;
-    private long mNextSrcId = mCurrentSrcId + 1;
-    private int mPlNextIndex = -1;
-    private int mPlNextSourceState = NEXT_SOURCE_STATE_INIT;
-    private boolean mPlNextSourcePlayPending = false;
+    private long mCurrentSrcId = mSrcIdGenerator++;
+    private List<DataSourceDesc> mNextDSDs;
+    private long mNextSrcId = mSrcIdGenerator++;
+    private int mNextSourceState = NEXT_SOURCE_STATE_INIT;
+    private boolean mNextSourcePlayPending = false;
+    //--- guarded by |mSrcLock| end
 
     // Modular DRM
-    private UUID mDrmUUID;
     private final Object mDrmLock = new Object();
+    //--- guarded by |mDrmLock| start
+    private UUID mDrmUUID;
     private DrmInfoImpl mDrmInfoImpl;
     private MediaDrm mDrmObj;
     private byte[] mDrmSessionId;
@@ -130,6 +133,7 @@
     private boolean mDrmProvisioningInProgress;
     private boolean mPrepareDrmInProgress;
     private ProvisioningThread mDrmProvisioningThread;
+    //--- guarded by |mDrmLock| end
 
     /**
      * Default constructor.
@@ -277,12 +281,6 @@
      * Gets the current player state.
      *
      * @return the current player state, one of the following:
-     * <ul>
-     * <li>{@link #PLAYER_STATE_IDLE}
-     * <li>{@link #PLAYER_STATE_PAUSED}
-     * <li>{@link #PLAYER_STATE_PLAYING}
-     * <li>{@link #PLAYER_STATE_ERROR}
-     * </ul>
      * @throws IllegalStateException if the internal player engine has not been
      * initialized or has been released.
      */
@@ -297,12 +295,6 @@
      * During buffering, see {@link #getBufferedPosition()} for the quantifying the amount already
      * buffered.
      * @return the buffering state, one of the following:
-     * <ul>
-     * <li>{@link #BUFFERING_STATE_UNKNOWN}
-     * <li>{@link #BUFFERING_STATE_BUFFERING_AND_PLAYABLE}
-     * <li>{@link #BUFFERING_STATE_BUFFERING_AND_STARVED}
-     * <li>{@link #BUFFERING_STATE_BUFFERING_COMPLETE}
-     * </ul>
      * @throws IllegalStateException if the internal player engine has not been
      * initialized or has been released.
      */
@@ -353,10 +345,12 @@
     @Override
     public void setDataSource(@NonNull DataSourceDesc dsd) {
         Preconditions.checkNotNull(dsd, "the DataSourceDesc cannot be null");
-        synchronized (mPlLock) {
+        // TODO: setDataSource could update exist data source
+        synchronized (mSrcLock) {
             mCurrentDSD = dsd;
+            mCurrentSrcId = mSrcIdGenerator++;
             try {
-                handleDataSource(true /* isCurrent */, dsd);
+                handleDataSource(true /* isCurrent */, dsd, mCurrentSrcId);
             } catch (IOException e) {
             }
         }
@@ -374,7 +368,19 @@
     public void setNextDataSource(@NonNull DataSourceDesc dsd) {
         Preconditions.checkNotNull(dsd, "the DataSourceDesc cannot be null");
 
-        // TODO: save dsd in a list
+        synchronized (mSrcLock) {
+            mNextDSDs = new ArrayList<DataSourceDesc>(1);
+            mNextDSDs.add(dsd);
+            mNextSrcId = mSrcIdGenerator++;
+            mNextSourceState = NEXT_SOURCE_STATE_INIT;
+            mNextSourcePlayPending = false;
+        }
+        int state = getMediaPlayer2State();
+        if (state != MEDIAPLAYER2_STATE_IDLE) {
+            synchronized (mSrcLock) {
+                prepareNextDataSource_l();
+            }
+        }
     }
 
     /**
@@ -386,45 +392,33 @@
      */
     @Override
     public void setNextDataSources(@NonNull List<DataSourceDesc> dsds) {
-        // TODO: save the list.
-        /*
         if (dsds == null || dsds.size() == 0) {
             throw new IllegalArgumentException("data source list cannot be null or empty.");
         }
-        HashSet ids = new HashSet(pl.size());
-        for (DataSourceDesc dsd : pl) {
+        for (DataSourceDesc dsd : dsds) {
             if (dsd == null) {
-                throw new IllegalArgumentException("DataSourceDesc in playlist cannot be null.");
-            }
-            if (ids.add(dsd.getId()) == false) {
-                throw new IllegalArgumentException("DataSourceDesc Id in playlist should be unique.");
+                throw new IllegalArgumentException(
+                        "DataSourceDesc in the source list cannot be null.");
             }
         }
 
-        if (startIndex < 0) {
-            startIndex = 0;
-        } else if (startIndex >= pl.size()) {
-            startIndex = pl.size() - 1;
+        synchronized (mSrcLock) {
+            mNextDSDs = new ArrayList(dsds);
+            mNextSrcId = mSrcIdGenerator++;
+            mNextSourceState = NEXT_SOURCE_STATE_INIT;
+            mNextSourcePlayPending = false;
         }
-
-        synchronized (mPlLock) {
-            mPlaylist = Collections.synchronizedList(new ArrayList(pl));
-            handleDataSource(true, mPlaylist.get(startIndex));
-            // TODO: handle the preparation of next source in the playlist.
-            // It should be processed after current source is prepared.
-            mPlNextIndex = getNextIndex_l();
+        int state = getMediaPlayer2State();
+        if (state != MEDIAPLAYER2_STATE_IDLE) {
+            synchronized (mSrcLock) {
+                prepareNextDataSource_l();
+            }
         }
-        */
     }
 
-    /**
-     * Gets the current data source as described by a DataSourceDesc.
-     *
-     * @return the current DataSourceDesc
-     */
     @Override
     public @NonNull DataSourceDesc getCurrentDataSource() {
-        synchronized (mPlLock) {
+        synchronized (mSrcLock) {
             return mCurrentDSD;
         }
     }
@@ -701,20 +695,20 @@
     public void clearPendingCommands() {
     }
 
-    private void handleDataSource(boolean isCurrent, @NonNull DataSourceDesc dsd)
+    private void handleDataSource(boolean isCurrent, @NonNull DataSourceDesc dsd, long srcId)
             throws IOException {
         Preconditions.checkNotNull(dsd, "the DataSourceDesc cannot be null");
 
         switch (dsd.getType()) {
             case DataSourceDesc.TYPE_CALLBACK:
                 handleDataSource(isCurrent,
-                                 0,  // TODO: get mapped Id
+                                 srcId,
                                  dsd.getMedia2DataSource());
                 break;
 
             case DataSourceDesc.TYPE_FD:
                 handleDataSource(isCurrent,
-                                 0,  // TODO: get mapped Id
+                                 srcId,
                                  dsd.getFileDescriptor(),
                                  dsd.getFileDescriptorOffset(),
                                  dsd.getFileDescriptorLength());
@@ -722,7 +716,7 @@
 
             case DataSourceDesc.TYPE_URI:
                 handleDataSource(isCurrent,
-                                 0,  // TODO: get mapped Id
+                                 srcId,
                                  dsd.getUriContext(),
                                  dsd.getUri(),
                                  dsd.getUriHeaders(),
@@ -899,16 +893,17 @@
     private native void nativeHandleDataSourceCallback(
             boolean isCurrent, long srcId, Media2DataSource dataSource);
 
-    // This function shall be called with |mPlLock| acquired.
+    // This function shall be called with |mSrcLock| acquired.
     private void prepareNextDataSource_l() {
-        if (mPlNextIndex < 0 || mPlNextSourceState != NEXT_SOURCE_STATE_INIT) {
+        if (mNextDSDs == null || mNextDSDs.isEmpty()
+                || mNextSourceState != NEXT_SOURCE_STATE_INIT) {
             // There is no next source or it's in preparing or prepared state.
             return;
         }
 
         try {
-            mPlNextSourceState = NEXT_SOURCE_STATE_PREPARING;
-            handleDataSource(false /* isCurrent */, mPlaylist.get(0));
+            mNextSourceState = NEXT_SOURCE_STATE_PREPARING;
+            handleDataSource(false /* isCurrent */, mNextDSDs.get(0), mNextSrcId);
         } catch (Exception e) {
             Message msg2 = mEventHandler.obtainMessage(
                     MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, null);
@@ -922,18 +917,20 @@
         }
     }
 
-    // This function shall be called with |mPlLock| acquired.
+    // This function shall be called with |mSrcLock| acquired.
     private void playNextDataSource_l() {
-        if (mPlNextIndex < 0) {
+        if (mNextDSDs == null || mNextDSDs.isEmpty()) {
             return;
         }
 
-        if (mPlNextSourceState == NEXT_SOURCE_STATE_PREPARED) {
+        if (mNextSourceState == NEXT_SOURCE_STATE_PREPARED) {
             // Switch to next source only when it's in prepared state.
+            mCurrentDSD = mNextDSDs.get(0);
             mCurrentSrcId = mNextSrcId;
-            mNextSrcId = 0; // TODO; fix it
-            mPlNextSourceState = NEXT_SOURCE_STATE_INIT;
-            mPlNextSourcePlayPending = false;
+            mNextDSDs.remove(0);
+            mNextSrcId = mSrcIdGenerator++;  // make it different from mCurrentSrcId
+            mNextSourceState = NEXT_SOURCE_STATE_INIT;
+            mNextSourcePlayPending = false;
 
             long srcId = mCurrentSrcId;
             try {
@@ -951,10 +948,10 @@
 
             // Wait for MEDIA2_INFO_STARTED_AS_NEXT to prepare next source.
         } else {
-            if (mPlNextSourceState == NEXT_SOURCE_STATE_INIT) {
+            if (mNextSourceState == NEXT_SOURCE_STATE_INIT) {
                 prepareNextDataSource_l();
             }
-            mPlNextSourcePlayPending = true;
+            mNextSourcePlayPending = true;
         }
     }
 
@@ -1245,26 +1242,13 @@
     @Override
     public native boolean isPlaying();
 
-    /**
-     * Gets the current MediaPlayer2 state.
-     *
-     * @return the current MediaPlayer2 state, one of the following:
-     * <ul>
-     * <li>{@link #MEDIAPLAYER2_STATE_IDLE}
-     * <li>{@link #MEDIAPLAYER2_STATE_PREPARED}
-     * <li>{@link #MEDIAPLAYER2_STATE_PAUSED}
-     * <li>{@link #MEDIAPLAYER2_STATE_PLAYING}
-     * <li>{@link #MEDIAPLAYER2_STATE_ERROR}
-     * </ul>
-     * @throws IllegalStateException if the internal player engine has not been
-     * initialized or has been released.
-     */
     @Override
     public @MediaPlayer2State int getMediaPlayer2State() {
-        // TODO: get state from native layer or cached value.
-        return MEDIAPLAYER2_STATE_IDLE;
+        return native_getMediaPlayer2State();
     }
 
+    private native int native_getMediaPlayer2State();
+
     /**
      * Gets the current buffering management params used by the source component.
      * Calling it only after {@code setDataSource} has been called.
@@ -2612,8 +2596,10 @@
             }
             final int what = msg.arg1;
             final int extra = msg.arg2;
+
             switch(msg.what) {
             case MEDIA_PREPARED:
+            {
                 try {
                     scanInternalSubtitleTracks();
                 } catch (RuntimeException e) {
@@ -2626,32 +2612,37 @@
                 }
 
                 final DataSourceDesc dsd;
-                synchronized (mPlLock) {
+                synchronized (mSrcLock) {
                     Log.i(TAG, "MEDIA_PREPARED: srcId=" + srcId
                             + ", currentSrcId=" + mCurrentSrcId + ", nextSrcId=" + mNextSrcId);
                     if (srcId == mCurrentSrcId) {
-                        prepareNextDataSource_l();
                         dsd = mCurrentDSD;
-                    } else if (mPlNextIndex >= 0 && srcId == mNextSrcId) {
-                        mPlNextSourceState = NEXT_SOURCE_STATE_PREPARED;
-                        if (mPlNextSourcePlayPending) {
+                        prepareNextDataSource_l();
+                    } else if (mNextDSDs != null && !mNextDSDs.isEmpty()
+                            && srcId == mNextSrcId) {
+                        dsd = mNextDSDs.get(0);
+                        mNextSourceState = NEXT_SOURCE_STATE_PREPARED;
+                        if (mNextSourcePlayPending) {
                             playNextDataSource_l();
                         }
-                        dsd = mPlaylist.get(0);
                     } else {
                         dsd = null;
                     }
                 }
 
-                synchronized (mEventCbLock) {
-                    for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) {
-                        cb.first.execute(() -> cb.second.onInfo(
-                                mMediaPlayer, dsd, MEDIA_INFO_PREPARED, 0));
+                if (dsd != null) {
+                    synchronized (mEventCbLock) {
+                        for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) {
+                            cb.first.execute(() -> cb.second.onInfo(
+                                    mMediaPlayer, dsd, MEDIA_INFO_PREPARED, 0));
+                        }
                     }
                 }
                 return;
+            }
 
             case MEDIA_DRM_INFO:
+            {
                 if (msg.obj == null) {
                     Log.w(TAG, "MEDIA_DRM_INFO msg.obj=NULL");
                 } else if (msg.obj instanceof Parcel) {
@@ -2679,9 +2670,12 @@
                     Log.w(TAG, "MEDIA_DRM_INFO msg.obj of unexpected type " + msg.obj);
                 }
                 return;
+            }
 
             case MEDIA_PLAYBACK_COMPLETE:
-                synchronized (mPlLock) {
+            {
+                final DataSourceDesc dsd = mCurrentDSD;
+                synchronized (mSrcLock) {
                     if (srcId == mCurrentSrcId) {
                         Log.i(TAG, "MEDIA_PLAYBACK_COMPLETE: srcId=" + srcId
                                 + ", currentSrcId=" + mCurrentSrcId + ", nextSrcId=" + mNextSrcId);
@@ -2692,32 +2686,34 @@
                 synchronized (mEventCbLock) {
                     for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) {
                         cb.first.execute(() -> cb.second.onInfo(
-                                mMediaPlayer, mCurrentDSD, MEDIA_INFO_PLAYBACK_COMPLETE, 0));
+                                mMediaPlayer, dsd, MEDIA_INFO_PLAYBACK_COMPLETE, 0));
                     }
                 }
                 stayAwake(false);
                 return;
+            }
 
             case MEDIA_STOPPED:
-                {
-                    TimeProvider timeProvider = mTimeProvider;
-                    if (timeProvider != null) {
-                        timeProvider.onStopped();
-                    }
+            {
+                TimeProvider timeProvider = mTimeProvider;
+                if (timeProvider != null) {
+                    timeProvider.onStopped();
                 }
                 break;
+            }
 
             case MEDIA_STARTED:
             case MEDIA_PAUSED:
-                {
-                    TimeProvider timeProvider = mTimeProvider;
-                    if (timeProvider != null) {
-                        timeProvider.onPaused(msg.what == MEDIA_PAUSED);
-                    }
+            {
+                TimeProvider timeProvider = mTimeProvider;
+                if (timeProvider != null) {
+                    timeProvider.onPaused(msg.what == MEDIA_PAUSED);
                 }
                 break;
+            }
 
             case MEDIA_BUFFERING_UPDATE:
+            {
                 final int percent = msg.arg1;
                 synchronized (mEventCbLock) {
                     for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) {
@@ -2726,26 +2722,30 @@
                     }
                 }
                 return;
+            }
 
             case MEDIA_SEEK_COMPLETE:
+            {
                 synchronized (mEventCbLock) {
                     for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) {
                         cb.first.execute(() -> cb.second.onCallComplete(
                                 mMediaPlayer, mCurrentDSD, MEDIA_CALL_SEEK_TO, 0));
                     }
                 }
+            }
                 // fall through
 
             case MEDIA_SKIPPED:
-                {
-                    TimeProvider timeProvider = mTimeProvider;
-                    if (timeProvider != null) {
-                        timeProvider.onSeekComplete(mMediaPlayer);
-                    }
+            {
+                TimeProvider timeProvider = mTimeProvider;
+                if (timeProvider != null) {
+                    timeProvider.onSeekComplete(mMediaPlayer);
                 }
                 return;
+            }
 
             case MEDIA_SET_VIDEO_SIZE:
+            {
                 final int width = msg.arg1;
                 final int height = msg.arg2;
                 synchronized (mEventCbLock) {
@@ -2755,8 +2755,10 @@
                     }
                 }
                 return;
+            }
 
             case MEDIA_ERROR:
+            {
                 Log.e(TAG, "Error (" + msg.arg1 + "," + msg.arg2 + ")");
                 synchronized (mEventCbLock) {
                     for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) {
@@ -2768,8 +2770,10 @@
                 }
                 stayAwake(false);
                 return;
+            }
 
             case MEDIA_INFO:
+            {
                 switch (msg.arg1) {
                     case MEDIA_INFO_STARTED_AS_NEXT:
                         if (srcId == mCurrentSrcId) {
@@ -2817,15 +2821,19 @@
                 }
                 // No real default action so far.
                 return;
+            }
 
             case MEDIA_NOTIFY_TIME:
-                    TimeProvider timeProvider = mTimeProvider;
-                    if (timeProvider != null) {
-                        timeProvider.onNotifyTime();
-                    }
+            {
+                TimeProvider timeProvider = mTimeProvider;
+                if (timeProvider != null) {
+                    timeProvider.onNotifyTime();
+                }
                 return;
+            }
 
             case MEDIA_TIMED_TEXT:
+            {
                 final TimedText text;
                 if (msg.obj instanceof Parcel) {
                     Parcel parcel = (Parcel)msg.obj;
@@ -2841,8 +2849,10 @@
                     }
                 }
                 return;
+            }
 
             case MEDIA_SUBTITLE_DATA:
+            {
                 OnSubtitleDataListener onSubtitleDataListener = mOnSubtitleDataListener;
                 if (onSubtitleDataListener == null) {
                     return;
@@ -2854,8 +2864,10 @@
                     onSubtitleDataListener.onSubtitleData(mMediaPlayer, data);
                 }
                 return;
+            }
 
             case MEDIA_META_DATA:
+            {
                 final TimedMetaData data;
                 if (msg.obj instanceof Parcel) {
                     Parcel parcel = (Parcel) msg.obj;
@@ -2872,11 +2884,15 @@
                     }
                 }
                 return;
+            }
 
             case MEDIA_NOP: // interface test message - ignore
+            {
                 break;
+            }
 
             case MEDIA_AUDIO_ROUTING_CHANGED:
+            {
                 AudioManager.resetAudioPortGeneration();
                 synchronized (mRoutingChangeListeners) {
                     for (NativeRoutingEventHandlerDelegate delegate
@@ -2885,11 +2901,14 @@
                     }
                 }
                 return;
+            }
 
             default:
+            {
                 Log.e(TAG, "Unknown message type " + msg.what);
                 return;
             }
+            }
         }
     }
 
@@ -3184,7 +3203,7 @@
 
             try {
                 // only creating the DRM object to allow pre-openSession configuration
-                prepareDrm(uuid);
+                prepareDrm_createDrmStep(uuid);
             } catch (Exception e) {
                 Log.w(TAG, "prepareDrm(): Exception ", e);
                 mPrepareDrmInProgress = false;
diff --git a/media/java/android/media/MediaPlayerBase.java b/media/java/android/media/MediaPlayerBase.java
index 3739847..24274f1 100644
--- a/media/java/android/media/MediaPlayerBase.java
+++ b/media/java/android/media/MediaPlayerBase.java
@@ -114,6 +114,11 @@
     public abstract void pause();
 
     /**
+     * Resets the MediaPlayerBase to its uninitialized state.
+     */
+    public abstract void reset();
+
+    /**
      *
      */
     public abstract void skipToNext();
diff --git a/media/java/android/media/MediaSession2.java b/media/java/android/media/MediaSession2.java
index ae5a8c6..d94be66 100644
--- a/media/java/android/media/MediaSession2.java
+++ b/media/java/android/media/MediaSession2.java
@@ -24,7 +24,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.media.MediaPlayerBase.PlayerEventCallback;
-import android.media.MediaPlaylistController;
 import android.media.session.MediaSession;
 import android.media.session.MediaSession.Callback;
 import android.media.session.PlaybackState;
@@ -82,10 +81,6 @@
 public class MediaSession2 implements AutoCloseable, MediaPlaylistController {
     private final MediaSession2Provider mProvider;
 
-    // TODO(jaewan): Should we define IntDef? Currently we don't have to allow subclass to add more.
-    // TODO(jaewan): Shouldn't we pull out?
-    // TODO(jaewan): Should we also protect getters not related with metadata?
-    //               Getters are getPlaybackState(), getSessionActivity(), getPlaylistParams()
     // Next ID: 23
     /**
      * Command code for the custom command which can be defined by string action in the
@@ -97,7 +92,7 @@
      * Command code for {@link MediaController2#play()}.
      * <p>
      * Command would be sent directly to the player if the session doesn't reject the request
-     * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+     * through the {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, Command)}.
      */
     public static final int COMMAND_CODE_PLAYBACK_PLAY = 1;
 
@@ -105,7 +100,7 @@
      * Command code for {@link MediaController2#pause()}.
      * <p>
      * Command would be sent directly to the player if the session doesn't reject the request
-     * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+     * through the {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, Command)}.
      */
     public static final int COMMAND_CODE_PLAYBACK_PAUSE = 2;
 
@@ -113,7 +108,7 @@
      * Command code for {@link MediaController2#stop()}.
      * <p>
      * Command would be sent directly to the player if the session doesn't reject the request
-     * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+     * through the {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, Command)}.
      */
     public static final int COMMAND_CODE_PLAYBACK_STOP = 3;
 
@@ -121,7 +116,7 @@
      * Command code for {@link MediaController2#skipToNext()}.
      * <p>
      * Command would be sent directly to the player if the session doesn't reject the request
-     * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+     * through the {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, Command)}.
      */
     public static final int COMMAND_CODE_PLAYBACK_SKIP_NEXT_ITEM = 4;
 
@@ -129,7 +124,7 @@
      * Command code for {@link MediaController2#skipToPrevious()}.
      * <p>
      * Command would be sent directly to the player if the session doesn't reject the request
-     * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+     * through the {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, Command)}.
      */
     public static final int COMMAND_CODE_PLAYBACK_SKIP_PREV_ITEM = 5;
 
@@ -137,7 +132,7 @@
      * Command code for {@link MediaController2#prepare()}.
      * <p>
      * Command would be sent directly to the player if the session doesn't reject the request
-     * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+     * through the {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, Command)}.
      */
     public static final int COMMAND_CODE_PLAYBACK_PREPARE = 6;
 
@@ -146,7 +141,7 @@
      * <p>
      * This is transport control command. Command would be sent directly to the player if the
      * session doesn't reject the request through the
-     * {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+     * {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, Command)}.
      */
     public static final int COMMAND_CODE_PLAYBACK_FAST_FORWARD = 7;
 
@@ -154,7 +149,7 @@
      * Command code for {@link MediaController2#rewind()}.
      * <p>
      * Command would be sent directly to the player if the session doesn't reject the request
-     * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+     * through the {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, Command)}.
      */
     public static final int COMMAND_CODE_PLAYBACK_REWIND = 8;
 
@@ -162,14 +157,14 @@
      * Command code for {@link MediaController2#seekTo(long)}.
      * <p>
      * Command would be sent directly to the player if the session doesn't reject the request
-     * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+     * through the {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, Command)}.
      */
     public static final int COMMAND_CODE_PLAYBACK_SEEK_TO = 9;
     /**
      * Command code for {@link MediaController2#skipToPlaylistItem(MediaItem2)}.
      * <p>
      * Command would be sent directly to the player if the session doesn't reject the request
-     * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+     * through the {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, Command)}.
      */
     public static final int COMMAND_CODE_PLAYBACK_SKIP_TO_PLAYLIST_ITEM = 10;
 
@@ -177,7 +172,7 @@
      * Command code for {@link MediaController2#setPlaylistParams(PlaylistParams)}.
      * <p>
      * Command would be sent directly to the player if the session doesn't reject the request
-     * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+     * through the {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, Command)}.
      */
     public static final int COMMAND_CODE_PLAYBACK_SET_PLAYLIST_PARAMS = 11;
 
@@ -185,7 +180,7 @@
      * Command code for {@link MediaController2#addPlaylistItem(int, MediaItem2)}.
      * <p>
      * Command would be sent directly to the player if the session doesn't reject the request
-     * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+     * through the {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, Command)}.
      */
     public static final int COMMAND_CODE_PLAYLIST_ADD = 12;
 
@@ -193,7 +188,7 @@
      * Command code for {@link MediaController2#addPlaylistItem(int, MediaItem2)}.
      * <p>
      * Command would be sent directly to the player if the session doesn't reject the request
-     * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+     * through the {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, Command)}.
      */
     public static final int COMMAND_CODE_PLAYLIST_REMOVE = 13;
 
@@ -201,7 +196,7 @@
      * Command code for {@link MediaController2#getPlaylist()}.
      * <p>
      * Command would be sent directly to the player if the session doesn't reject the request
-     * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+     * through the {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, Command)}.
      */
     public static final int COMMAND_CODE_PLAYLIST_GET = 14;
 
@@ -211,7 +206,7 @@
      * <p>
      * Command would adjust the volume or sent to the volume provider directly if the session
      * doesn't reject the request through the
-     * {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+     * {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, Command)}.
      */
     public static final int COMMAND_CODE_SET_VOLUME = 15;
 
@@ -339,7 +334,6 @@
      * If {@link #getCommandCode()} is {@link #COMMAND_CODE_CUSTOM}), it's custom command and
      * {@link #getCustomCommand()} shouldn't be {@code null}.
      */
-    // TODO(jaewan): Move this into the updatable.
     public static final class Command {
         private final CommandProvider mProvider;
 
@@ -435,8 +429,7 @@
         }
 
         public List<Command> getCommands() {
-            // TODO: implement this
-            return null;
+            return mProvider.getCommands_impl();
         }
 
         /**
@@ -470,7 +463,7 @@
      * If it's not set, the session will accept all controllers and all incoming commands by
      * default.
      */
-    // TODO(jaewan): Can we move this inside of the updatable for default implementation.
+    // TODO(jaewan): Move this to updatable for default implementation (b/74091963)
     public static abstract class SessionCallback {
         private final Context mContext;
 
@@ -483,13 +476,15 @@
          * controller. By default it allows all connection requests and commands.
          * <p>
          * You can reject the connection by return {@code null}. In that case, controller receives
-         * {@link MediaController2.ControllerCallback#onDisconnected()} and cannot be usable.
+         * {@link MediaController2.ControllerCallback#onDisconnected(MediaController2)} and cannot
+         * be usable.
          *
+         * @param session the session for this event
          * @param controller controller information.
          * @return allowed commands. Can be {@code null} to reject coonnection.
          */
-        // TODO(jaewan): Change return type. Once we do, null is for reject.
-        public @Nullable CommandGroup onConnect(@NonNull ControllerInfo controller) {
+        public @Nullable CommandGroup onConnect(@NonNull MediaSession2 session,
+                @NonNull ControllerInfo controller) {
             CommandGroup commands = new CommandGroup(mContext);
             commands.addAllPredefinedCommands();
             return commands;
@@ -498,14 +493,17 @@
         /**
          * Called when a controller is disconnected
          *
+         * @param session the session for this event
          * @param controller controller information
          */
-        public void onDisconnected(@NonNull ControllerInfo controller) { }
+        public void onDisconnected(@NonNull MediaSession2 session,
+                @NonNull ControllerInfo controller) { }
 
         /**
          * Called when a controller sent a command that will be sent directly to the player. Return
          * {@code false} here to reject the request and stop sending command to the player.
          *
+         * @param session the session for this event
          * @param controller controller information.
          * @param command a command. This method will be called for every single command.
          * @return {@code true} if you want to accept incoming command. {@code false} otherwise.
@@ -525,8 +523,8 @@
          * @see #COMMAND_CODE_PLAYLIST_GET
          * @see #COMMAND_CODE_SET_VOLUME
          */
-        public boolean onCommandRequest(@NonNull ControllerInfo controller,
-                @NonNull Command command) {
+        public boolean onCommandRequest(@NonNull MediaSession2 session,
+                @NonNull ControllerInfo controller, @NonNull Command command) {
             return true;
         }
 
@@ -539,37 +537,41 @@
          * in order to provide possible rating style for controller. Controller will follow the
          * rating style.
          *
+         * @param session the session for this event
          * @param controller controller information
          * @param mediaId media id from the controller
          * @param rating new rating from the controller
          */
-        public void onSetRating(@NonNull ControllerInfo controller, @NonNull String mediaId,
-                @NonNull Rating2 rating) { }
+        public void onSetRating(@NonNull MediaSession2 session, @NonNull ControllerInfo controller,
+                @NonNull String mediaId, @NonNull Rating2 rating) { }
 
         /**
          * Called when a controller sent a custom command through
          * {@link MediaController2#sendCustomCommand(Command, Bundle, ResultReceiver)}.
          *
+         * @param session the session for this event
          * @param controller controller information
          * @param customCommand custom command.
          * @param args optional arguments
          * @param cb optional result receiver
          */
-        public void onCustomCommand(@NonNull ControllerInfo controller,
-                @NonNull Command customCommand, @Nullable Bundle args,
-                @Nullable ResultReceiver cb) { }
+        public void onCustomCommand(@NonNull MediaSession2 session,
+                @NonNull ControllerInfo controller, @NonNull Command customCommand,
+                @Nullable Bundle args, @Nullable ResultReceiver cb) { }
 
         /**
          * Called when a controller requested to play a specific mediaId through
          * {@link MediaController2#playFromMediaId(String, Bundle)}.
          *
+         * @param session the session for this event
          * @param controller controller information
          * @param mediaId media id
          * @param extras optional extra bundle
          * @see #COMMAND_CODE_PLAY_FROM_MEDIA_ID
          */
-        public void onPlayFromMediaId(@NonNull ControllerInfo controller,
-                @NonNull String mediaId, @Nullable Bundle extras) { }
+        public void onPlayFromMediaId(@NonNull MediaSession2 session,
+                @NonNull ControllerInfo controller, @NonNull String mediaId,
+                @Nullable Bundle extras) { }
 
         /**
          * Called when a controller requested to begin playback from a search query through
@@ -578,25 +580,29 @@
          * An empty query indicates that the app may play any music. The implementation should
          * attempt to make a smart choice about what to play.
          *
+         * @param session the session for this event
          * @param controller controller information
          * @param query query string. Can be empty to indicate any suggested media
          * @param extras optional extra bundle
          * @see #COMMAND_CODE_PLAY_FROM_SEARCH
          */
-        public void onPlayFromSearch(@NonNull ControllerInfo controller,
-                @NonNull String query, @Nullable Bundle extras) { }
+        public void onPlayFromSearch(@NonNull MediaSession2 session,
+                @NonNull ControllerInfo controller, @NonNull String query,
+                @Nullable Bundle extras) { }
 
         /**
          * Called when a controller requested to play a specific media item represented by a URI
          * through {@link MediaController2#playFromUri(Uri, Bundle)}
          *
+         * @param session the session for this event
          * @param controller controller information
          * @param uri uri
          * @param extras optional extra bundle
          * @see #COMMAND_CODE_PLAY_FROM_URI
          */
-        public void onPlayFromUri(@NonNull ControllerInfo controller,
-                @NonNull Uri uri, @Nullable Bundle extras) { }
+        public void onPlayFromUri(@NonNull MediaSession2 session,
+                @NonNull ControllerInfo controller, @NonNull Uri uri,
+                @Nullable Bundle extras) { }
 
         /**
          * Called when a controller requested to prepare for playing a specific mediaId through
@@ -612,13 +618,15 @@
          * Override {@link #onPlayFromMediaId} to handle requests for starting
          * playback without preparation.
          *
+         * @param session the session for this event
          * @param controller controller information
          * @param mediaId media id to prepare
          * @param extras optional extra bundle
          * @see #COMMAND_CODE_PREPARE_FROM_MEDIA_ID
          */
-        public void onPrepareFromMediaId(@NonNull ControllerInfo controller,
-                @NonNull String mediaId, @Nullable Bundle extras) { }
+        public void onPrepareFromMediaId(@NonNull MediaSession2 session,
+                @NonNull ControllerInfo controller, @NonNull String mediaId,
+                @Nullable Bundle extras) { }
 
         /**
          * Called when a controller requested to prepare playback from a search query through
@@ -634,13 +642,15 @@
          * Override {@link #onPlayFromSearch} to handle requests for starting playback without
          * preparation.
          *
+         * @param session the session for this event
          * @param controller controller information
          * @param query query string. Can be empty to indicate any suggested media
          * @param extras optional extra bundle
          * @see #COMMAND_CODE_PREPARE_FROM_SEARCH
          */
-        public void onPrepareFromSearch(@NonNull ControllerInfo controller,
-                @NonNull String query, @Nullable Bundle extras) { }
+        public void onPrepareFromSearch(@NonNull MediaSession2 session,
+                @NonNull ControllerInfo controller, @NonNull String query,
+                @Nullable Bundle extras) { }
 
         /**
          * Called when a controller requested to prepare a specific media item represented by a URI
@@ -656,13 +666,14 @@
          * Override {@link #onPlayFromUri} to handle requests for starting playback without
          * preparation.
          *
+         * @param session the session for this event
          * @param controller controller information
          * @param uri uri
          * @param extras optional extra bundle
          * @see #COMMAND_CODE_PREPARE_FROM_URI
          */
-        public void onPrepareFromUri(@NonNull ControllerInfo controller,
-                @NonNull Uri uri, @Nullable Bundle extras) { }
+        public void onPrepareFromUri(@NonNull MediaSession2 session,
+                @NonNull ControllerInfo controller, @NonNull Uri uri, @Nullable Bundle extras) { }
     };
 
     /**
@@ -698,7 +709,7 @@
          * @param player a {@link MediaPlayerBase} that handles actual media playback in your app.
          */
         U setPlayer(@NonNull MediaPlayerBase player) {
-            // TODO: Change the provider properly
+            // TODO(jaewan): Change the provider properly (b/74093082)
             mProvider.setPlayer_impl(player, null, null);
             return (U) this;
         }
@@ -711,7 +722,7 @@
          * {@code player.}
          */
         U setPlaylistController(@NonNull MediaPlaylistController mplc) {
-            // TODO: implement this
+            // TODO(jaewan): implement this (b/74093082)
             return (U) this;
         }
 
@@ -722,7 +733,7 @@
          * @param volumeProvider The provider that will receive volume button events.
          */
         U setVolumeProvider(@NonNull VolumeProvider2 volumeProvider) {
-            // TODO: implement this
+            // TODO(jaewan): implement this (b/74093082)
             return (U) this;
         }
 
@@ -847,7 +858,6 @@
         /**
          * @hide
          */
-        // TODO(jaewan): Also accept componentName to check notificaiton listener.
         public ControllerInfo(Context context, int uid, int pid, String packageName,
                 IInterface callback) {
             mProvider = ApiLoader.getProvider(context)
@@ -894,18 +904,12 @@
 
         @Override
         public boolean equals(Object obj) {
-            if (!(obj instanceof ControllerInfo)) {
-                return false;
-            }
-            ControllerInfo other = (ControllerInfo) obj;
-            return mProvider.equals_impl(other.mProvider);
+            return mProvider.equals_impl(obj);
         }
 
         @Override
         public String toString() {
-            // TODO(jaewan): Move this to updatable.
-            return "ControllerInfo {pkg=" + getPackageName() + ", uid=" + getUid() + ", trusted="
-                    + isTrusted() + "}";
+            return mProvider.toString_impl();
         }
     }
 
@@ -1175,14 +1179,13 @@
      *
      * @param player a {@link MediaPlayerBase} that handles actual media playback in your app.
      * @param mplc a {@link MediaPlaylistController} that manages playlist of the
-     * {@code player.}
+     * {@code player}
      * @param volumeProvider The provider that will receive volume button events. If
      * {@code null}, system will adjust the appropriate stream volume for this session's player.
      */
     public void updatePlayer(@NonNull MediaPlayerBase player,
-            @Nullable MediaPlaylistController mplc, @NonNull VolumeProvider2 volumeProvider) {
-        // TODO: rename setPlayer_impl to updatePlayer_impl
-        mProvider.setPlayer_impl(player, mplc, volumeProvider);
+            @Nullable MediaPlaylistController mplc, @Nullable VolumeProvider2 volumeProvider) {
+        mProvider.updatePlayer_impl(player, mplc, volumeProvider);
     }
 
     @Override
@@ -1201,19 +1204,16 @@
     /**
      * @return playlist controller
      */
-    public @Nullable
-    MediaPlaylistController getMediaPlaylistController() {
-        // TODO: implement this
+    public @Nullable MediaPlaylistController getMediaPlaylistController() {
+        // TODO(jaewan): implement this (b/74090741)
         return null;
     }
 
     /**
      * @return volume provider
      */
-    public @Nullable
-    VolumeProvider2 getVolumeProvider() {
-     // TODO: implement this
-        return null;
+    public @Nullable VolumeProvider2 getVolumeProvider() {
+        return mProvider.getVolumeProvider_impl();
     }
 
     /**
@@ -1234,7 +1234,7 @@
      * @param afr the full request parameters
      */
     public void setAudioFocusRequest(AudioFocusRequest afr) {
-        // TODO: implement this
+        // TODO(jaewan): implement this (b/72529899)
         // mProvider.setAudioFocusRequest_impl(focusGain);
     }
 
@@ -1252,7 +1252,7 @@
      *      expanded row:   layout[5] layout[6] layout[7] layout[8] layout[9]
      *      main row:       layout[3] layout[1] layout[0] layout[2] layout[4]
      * <p>
-     * This API can be called in the {@link SessionCallback#onConnect(ControllerInfo)}.
+     * This API can be called in the {@link SessionCallback#onConnect(MediaSession2, ControllerInfo)}.
      *
      * @param controller controller to specify layout.
      * @param layout oredered list of layout.
@@ -1408,8 +1408,6 @@
      *
      * @throws IllegalArgumentException if the play list is null
      */
-    // TODO(jaewan): Remove with index was previously rejected by council (b/36524925)
-    // TODO(jaewan): Should we also add movePlaylistItem from index to index?
     public void removePlaylistItem(MediaItem2 item) {
         mProvider.removePlaylistItem_impl(item);
     }
@@ -1500,7 +1498,7 @@
      * @throws IllegalArgumentException if executor or callback is {@code null}.
      * @hide
      */
-    // TODO(jaewan): Unhide or remove
+    // TODO(jaewan): Remove (b/74157064)
     public void registerPlayerEventCallback(@NonNull @CallbackExecutor Executor executor,
             @NonNull PlayerEventCallback callback) {
         mProvider.registerPlayerEventCallback_impl(executor, callback);
@@ -1513,7 +1511,7 @@
      * @throws IllegalArgumentException if the callback is {@code null}.
      * @hide
      */
-    // TODO(jaewan): Unhide or remove
+    // TODO(jaewan): Remove (b/74157064)
     public void unregisterPlayerEventCallback(@NonNull PlayerEventCallback callback) {
         mProvider.unregisterPlayerEventCallback_impl(callback);
     }
@@ -1534,7 +1532,7 @@
      * @return speed
      */
     public float getPlaybackSpeed() {
-        // TODO: implement this
+        // TODO(jaewan): implement this (b/74093080)
         return -1;
     }
 
@@ -1542,6 +1540,6 @@
      * Set the playback speed.
      */
     public void setPlaybackSpeed(float speed) {
-        // TODO: implement this
+        // TODO(jaewan): implement this (b/74093080)
     }
 }
diff --git a/media/java/android/media/MediaSessionService2.java b/media/java/android/media/MediaSessionService2.java
index 56e8e5d..9032e0e 100644
--- a/media/java/android/media/MediaSessionService2.java
+++ b/media/java/android/media/MediaSessionService2.java
@@ -85,7 +85,8 @@
  * session service, the controller binds to the session service. {@link #onCreateSession(String)}
  * may be called after the {@link #onCreate} if the service hasn't created yet.
  * <p>
- * After the binding, session's {@link MediaSession2.SessionCallback#onConnect(ControllerInfo)}
+ * After the binding, session's {@link MediaSession2.SessionCallback#onConnect(MediaSession2, ControllerInfo)}
+ *
  * will be called to accept or reject connection request from a controller. If the connection is
  * rejected, the controller will unbind. If it's accepted, the controller will be available to use
  * and keep binding.
@@ -99,7 +100,7 @@
  * <p>
  * Any app can bind to the session service with controller, but the controller can be used only if
  * the session service accepted the connection request through
- * {@link MediaSession2.SessionCallback#onConnect(ControllerInfo)}.
+ * {@link MediaSession2.SessionCallback#onConnect(MediaSession2, ControllerInfo)}.
  */
 public abstract class MediaSessionService2 extends Service {
     private final MediaSessionService2Provider mProvider;
diff --git a/media/java/android/media/PlaybackState2.java b/media/java/android/media/PlaybackState2.java
index 7afb579..afc2bfa 100644
--- a/media/java/android/media/PlaybackState2.java
+++ b/media/java/android/media/PlaybackState2.java
@@ -33,7 +33,7 @@
  * the current playback position and extra.
  * @hide
  */
-// TODO(jaewan): Remove this.
+// TODO(jaewan): Remove this (b/73971431)
 public final class PlaybackState2 {
     // Similar to the PlaybackState with following changes
     //    - Not implement Parcelable and added from/toBundle()
@@ -76,7 +76,6 @@
     //    - Removed actions and custom actions.
     //    - Removed error string
     //    - Repeat mode / shuffle mode is now in the PlaylistParams
-    // TODO(jaewan): Replace states from MediaPlayer2
     /**
      * @hide
      */
diff --git a/media/java/android/media/update/MediaSession2Provider.java b/media/java/android/media/update/MediaSession2Provider.java
index d0ec104..f97a6f0 100644
--- a/media/java/android/media/update/MediaSession2Provider.java
+++ b/media/java/android/media/update/MediaSession2Provider.java
@@ -44,9 +44,10 @@
  */
 public interface MediaSession2Provider extends TransportControlProvider {
     void close_impl();
-    void setPlayer_impl(MediaPlayerBase player, MediaPlaylistController mplc,
+    void updatePlayer_impl(MediaPlayerBase player, MediaPlaylistController mplc,
             VolumeProvider2 volumeProvider);
     MediaPlayerBase getPlayer_impl();
+    VolumeProvider2 getVolumeProvider_impl();
     SessionToken2 getToken_impl();
     List<ControllerInfo> getConnectedControllers_impl();
     void setCustomLayout_impl(ControllerInfo controller, List<CommandButton> layout);
@@ -84,6 +85,7 @@
         void removeCommand_impl(Command command);
         boolean hasCommand_impl(Command command);
         boolean hasCommand_impl(int code);
+        List<Command> getCommands_impl();
         Bundle toBundle_impl();
     }
 
@@ -109,7 +111,8 @@
         int getUid_impl();
         boolean isTrusted_impl();
         int hashCode_impl();
-        boolean equals_impl(ControllerInfoProvider obj);
+        boolean equals_impl(Object obj);
+        String toString_impl();
     }
 
     interface PlaylistParamsProvider {
diff --git a/media/jni/android_media_MediaPlayer2.cpp b/media/jni/android_media_MediaPlayer2.cpp
index b0936fb..af78777 100644
--- a/media/jni/android_media_MediaPlayer2.cpp
+++ b/media/jni/android_media_MediaPlayer2.cpp
@@ -777,6 +777,16 @@
 }
 
 static jint
+android_media_MediaPlayer2_getMediaPlayer2State(JNIEnv *env, jobject thiz)
+{
+    sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL) {
+        return MEDIAPLAYER2_STATE_IDLE;
+    }
+    return (jint)mp->getMediaPlayer2State();
+}
+
+static jint
 android_media_MediaPlayer2_getVideoWidth(JNIEnv *env, jobject thiz)
 {
     sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
@@ -1483,6 +1493,7 @@
     {"prepare",            "()V",                              (void *)android_media_MediaPlayer2_prepare},
     {"_start",              "()V",                              (void *)android_media_MediaPlayer2_start},
     {"_stop",               "()V",                              (void *)android_media_MediaPlayer2_stop},
+    {"native_getMediaPlayer2State", "()I",                      (void *)android_media_MediaPlayer2_getMediaPlayer2State},
     {"getVideoWidth",       "()I",                              (void *)android_media_MediaPlayer2_getVideoWidth},
     {"getVideoHeight",      "()I",                              (void *)android_media_MediaPlayer2_getVideoHeight},
     {"native_getMetrics",   "()Landroid/os/PersistableBundle;", (void *)android_media_MediaPlayer2_native_getMetrics},
diff --git a/native/android/asset_manager.cpp b/native/android/asset_manager.cpp
index 98e9a42..e70d5ea 100644
--- a/native/android/asset_manager.cpp
+++ b/native/android/asset_manager.cpp
@@ -18,9 +18,11 @@
 #include <utils/Log.h>
 
 #include <android/asset_manager_jni.h>
+#include <android_runtime/android_util_AssetManager.h>
 #include <androidfw/Asset.h>
 #include <androidfw/AssetDir.h>
 #include <androidfw/AssetManager.h>
+#include <androidfw/AssetManager2.h>
 #include <utils/threads.h>
 
 #include "jni.h"
@@ -35,21 +37,20 @@
 
 // -----
 struct AAssetDir {
-    AssetDir* mAssetDir;
+    std::unique_ptr<AssetDir> mAssetDir;
     size_t mCurFileIndex;
     String8 mCachedFileName;
 
-    explicit AAssetDir(AssetDir* dir) : mAssetDir(dir), mCurFileIndex(0) { }
-    ~AAssetDir() { delete mAssetDir; }
+    explicit AAssetDir(std::unique_ptr<AssetDir> dir) :
+        mAssetDir(std::move(dir)), mCurFileIndex(0) { }
 };
 
 
 // -----
 struct AAsset {
-    Asset* mAsset;
+    std::unique_ptr<Asset> mAsset;
 
-    explicit AAsset(Asset* asset) : mAsset(asset) { }
-    ~AAsset() { delete mAsset; }
+    explicit AAsset(std::unique_ptr<Asset> asset) : mAsset(std::move(asset)) { }
 };
 
 // -------------------- Public native C API --------------------
@@ -104,19 +105,18 @@
         return NULL;
     }
 
-    AssetManager* mgr = static_cast<AssetManager*>(amgr);
-    Asset* asset = mgr->open(filename, amMode);
-    if (asset == NULL) {
-        return NULL;
+    ScopedLock<AssetManager2> locked_mgr(*AssetManagerForNdkAssetManager(amgr));
+    std::unique_ptr<Asset> asset = locked_mgr->Open(filename, amMode);
+    if (asset == nullptr) {
+        return nullptr;
     }
-
-    return new AAsset(asset);
+    return new AAsset(std::move(asset));
 }
 
 AAssetDir* AAssetManager_openDir(AAssetManager* amgr, const char* dirName)
 {
-    AssetManager* mgr = static_cast<AssetManager*>(amgr);
-    return new AAssetDir(mgr->openDir(dirName));
+    ScopedLock<AssetManager2> locked_mgr(*AssetManagerForNdkAssetManager(amgr));
+    return new AAssetDir(locked_mgr->OpenDir(dirName));
 }
 
 /**
diff --git a/native/android/configuration.cpp b/native/android/configuration.cpp
index 77237ae..87fe9ed 100644
--- a/native/android/configuration.cpp
+++ b/native/android/configuration.cpp
@@ -17,9 +17,10 @@
 #define LOG_TAG "Configuration"
 #include <utils/Log.h>
 
-#include <androidfw/AssetManager.h>
+#include <androidfw/AssetManager2.h>
 
 #include <android_runtime/android_content_res_Configuration.h>
+#include <android_runtime/android_util_AssetManager.h>
 
 using namespace android;
 
@@ -34,7 +35,11 @@
 }
 
 void AConfiguration_fromAssetManager(AConfiguration* out, AAssetManager* am) {
-    ((AssetManager*)am)->getConfiguration(out);
+    ScopedLock<AssetManager2> locked_mgr(*AssetManagerForNdkAssetManager(am));
+    ResTable_config config = locked_mgr->GetConfiguration();
+
+    // AConfiguration is not a virtual subclass, so we can memcpy.
+    memcpy(out, &config, sizeof(config));
 }
 
 void AConfiguration_copy(AConfiguration* dest, AConfiguration* src) {
diff --git a/nfc-extras/Android.mk b/nfc-extras/Android.mk
index dc45a50..03de00c 100644
--- a/nfc-extras/Android.mk
+++ b/nfc-extras/Android.mk
@@ -1,13 +1,33 @@
 LOCAL_PATH:= $(call my-dir)
 
 include $(CLEAR_VARS)
-
+LOCAL_MODULE := com.android.nfc_extras
 LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-java-files-under, java)
-
-LOCAL_MODULE:= com.android.nfc_extras
-
+LOCAL_SRC_FILES := $(call all-java-files-under,java)
 include $(BUILD_JAVA_LIBRARY)
 
+include $(CLEAR_VARS)
+LOCAL_MODULE := com.android.nfc_extras-stubs-gen
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+LOCAL_SRC_FILES := $(call all-java-files-under,java)
+# This is to reference SdkConstant annotation; not part of this lib.
+LOCAL_DROIDDOC_SOURCE_PATH := frameworks/base/core/java/android/annotation
+LOCAL_DROIDDOC_STUB_OUT_DIR := $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/com.android.nfc_extras.stubs_intermediates/src
+LOCAL_DROIDDOC_OPTIONS:= \
+    -hide 111 -hide 113 -hide 125 -hide 126 -hide 127 -hide 128 \
+    -stubpackages com.android.nfc_extras \
+    -nodocs
+LOCAL_UNINSTALLABLE_MODULE := true
+include $(BUILD_DROIDDOC)
+com_android_nfc_extras_gen_stamp := $(full_target)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := com.android.nfc_extras.stubs
+# This is to reference SdkConstant annotation; not part of this lib.
+LOCAL_SRC_FILES := ../core/java/android/annotation/SdkConstant.java
+LOCAL_SDK_VERSION := current
+LOCAL_ADDITIONAL_DEPENDENCIES := $(com_android_nfc_extras_gen_stamp)
+com_android_nfc_extras_gen_stamp :=
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/nfc-extras/tests/Android.mk b/nfc-extras/tests/Android.mk
index 51396d3..8bba3ba 100644
--- a/nfc-extras/tests/Android.mk
+++ b/nfc-extras/tests/Android.mk
@@ -20,7 +20,7 @@
 
 LOCAL_JAVA_LIBRARIES := \
     android.test.runner.stubs \
-    com.android.nfc_extras \
+    com.android.nfc_extras.stubs \
     android.test.base.stubs
 
 LOCAL_STATIC_JAVA_LIBRARIES := junit
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index c166016..1d72349 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Private DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Kies private DNS-modus"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Af"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Opportunisties"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Gasheernaam van private DNS-verskaffer"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Voer gasheernaam van DNS-verskaffer in"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Wys opsies vir draadlose skermsertifisering"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Hierdie kenmerk is eksperimenteel en kan werkverrigting beïnvloed."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Geneutraliseer deur <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Omtrent <xliff:g id="TIME">%1$s</xliff:g> oor"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Ongeveer <xliff:g id="TIME">%1$s</xliff:g> oor gegrond op jou gebruik"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> oor tot vol gelaai"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> oor"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Minder as <xliff:g id="THRESHOLD">%1$s</xliff:g> oor"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – minder as <xliff:g id="THRESHOLD">%2$s</xliff:g> oor"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>meer as <xliff:g id="TIME_REMAINING">%2$s</xliff:g> oor"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"meer as <xliff:g id="TIME_REMAINING">%1$s</xliff:g> oor"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"foon kan binnekort afgaan"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet kan binnekort afgaan"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"toestel kan binnekort afgaan"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – omtrent <xliff:g id="TIME">%2$s</xliff:g> oor"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – ongeveer <xliff:g id="TIME">%2$s</xliff:g> oor gegrond op jou gebruik"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – foon kan binnekort afgaan"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – tablet kan binnekort afgaan"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – toestel kan binnekort afgaan"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> oor tot vol gelaai"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tot vol gelaai"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Onbekend"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Laai"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 6c8c69a..a8b48aa 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"የግል ዲኤንኤስ"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"የግል ዲኤንኤስ ሁነታ ይምረጡ"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"ጠፍቷል"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"አድርባይ"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"የግል ዲኤንኤስ አቅራቢ አስተናጋጅ ስም"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"የዲኤንኤስ አቅራቢ አስተናጋጅ ስም ያስገቡ"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"የገመድ አልባ ማሳያ እውቅና ማረጋገጫ አማራጮችን አሳይ"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ይህ ባህሪ የሙከራ ነውና አፈጻጸም ላይ ተጽዕኖ ሊኖረው ይችላል።"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"በ<xliff:g id="TITLE">%1$s</xliff:g> ተሽሯል"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"<xliff:g id="TIME">%1$s</xliff:g> አካባቢ ቀርቷል"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"በእርስዎ አጠቃቀም ላይ በመመስረት <xliff:g id="TIME">%1$s</xliff:g> ገደማ ቀርቷል"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"ሙሉ ኃይል እስኪሞላ ድረስ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> ቀርቷል"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"ከ<xliff:g id="THRESHOLD">%1$s</xliff:g> ያነሰ ይቀራል"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - ከ<xliff:g id="THRESHOLD">%2$s</xliff:g> በታች ይቀራል"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>ከ<xliff:g id="TIME_REMAINING">%2$s</xliff:g> የበለጠ ይቀራል"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"ከ<xliff:g id="TIME_REMAINING">%1$s</xliff:g> በላይ ይቀራል"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ስልኩ በቅርቡ ሊዘጋ ይችላል"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ጡባዊ በቅርቡ ሊዘጋ ይችል ይሆናል"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"መሣሪያ በቅርቡ ሊዘጋ ይችል ይሆናል"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> አካባቢ ይቀራል"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - በእርስዎ አጠቃቀም ላይ በመመስረት <xliff:g id="TIME">%2$s</xliff:g> ገደማ ቀርቷል"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - ስልክ በቅርቡ ሊዘጋ ይችል ይሆናል"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - ጡባዊ በቅርቡ ሊዘጋ ይችል ይሆናል"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - መሣሪያ በቅርቡ ሊዘጋ ይችል ይሆናል"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"ሙሉ ኃይል እስኪሞላ ድረስ <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - ሙሉ ለሙሉ እስኪሞላ ድረስ <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"ያልታወቀ"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"ኃይል በመሙላት ላይ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 40c16b9..7f4d643 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"نظام أسماء النطاقات الخاص"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"اختر وضع نظام أسماء النطاقات الخاص"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"غير مفعّل"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"انتهازي"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"اسم مضيف مزوّد نظام أسماء النطاقات الخاص"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"أدخل اسم مضيف مزوّد نظام أسماء النطاقات"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"عرض خيارات شهادة عرض شاشة لاسلكي"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"هذه الميزة تجريبية وقد تؤثر في الأداء."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"تم الاستبدال بـ <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"يتبقى حوالي <xliff:g id="TIME">%1$s</xliff:g> لإتمام شحن البطارية"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"يتبقى <xliff:g id="TIME">%1$s</xliff:g> تقريبًا بناءً على استخدامك"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"يتبقى <xliff:g id="TIME">%1$s</xliff:g> لشحن البطارية بالكامل"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"يتبقى <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"يتبقى أقل من <xliff:g id="THRESHOLD">%1$s</xliff:g>."</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - يتبقى أقل من <xliff:g id="THRESHOLD">%2$s</xliff:g>."</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>يتبقى أكثر من <xliff:g id="TIME_REMAINING">%2$s</xliff:g>."</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"يتبقى أكثر من <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"قد يتم إغلاق الهاتف بعد قليل."</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"قد يتم إغلاق الجهاز اللوحي بعد قليل."</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"قد يتم إغلاق الجهاز بعد قليل."</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - يتبقى <xliff:g id="TIME">%2$s</xliff:g> تقريبًا"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - يتبقى <xliff:g id="TIME">%2$s</xliff:g> تقريبًا بناءً على استخدامك"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - قد يتم إغلاق الهاتف بعد قليل."</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - قد يتم إغلاق الجهاز اللوحي بعد قليل."</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - قد يتم إغلاق الجهاز بعد قليل."</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"يتبقى <xliff:g id="TIME">%1$s</xliff:g> لشحن البطارية بالكامل"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> حتى يكتمل الشحن"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"غير معروف"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"جارٍ الشحن"</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index b4d1af8..c9dd0da 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -233,7 +233,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"ব্যক্তিগত DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"ব্যক্তিগত DNS ম\'ড বাছনি কৰক"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"অফ"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"সুবিধাবাদী"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"ব্যক্তিগত ডিএনএছ প্ৰদানকাৰীৰ হোষ্টনাম"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"ডিএনএছ সেৱা যোগানকাৰীৰ হ\'ষ্টনাম দিয়ক"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"বেতাঁৰ ডিছপ্লে প্ৰমাণপত্ৰৰ বাবে বিকল্পসমূহ দেখুৱাওক"</string>
@@ -372,32 +373,42 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"এই সুবিধাটো পৰীক্ষামূলক, সেয়ে ই কাৰ্যক্ষমতাৰ ওপৰত প্ৰভাৱ পেলাব পাৰে।"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g>ৰ দ্বাৰা অগ্ৰাহ্য কৰা হৈছে"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"প্ৰায় <xliff:g id="TIME">%1$s</xliff:g> বাকী আছে"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"আপোনাৰ ব্যৱহাৰৰ ওপৰত ভিত্তি কৰি প্ৰায় <xliff:g id="TIME">%1$s</xliff:g> বাকী আছে"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"সম্পূৰ্ণকৈ চ্চাৰ্জ হ\'বলৈ <xliff:g id="TIME">%1$s</xliff:g> বাকী"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> বাকী"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <!-- no translation found for power_remaining_less_than_duration_only (5996752448813295329) -->
     <skip />
-    <!-- no translation found for power_remaining_less_than_duration (7967078125657859046) -->
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
     <skip />
-    <!-- no translation found for power_remaining_more_than_subtext (6846716609975752316) -->
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
     <skip />
-    <!-- no translation found for power_remaining_only_more_than_subtext (8884488700395194194) -->
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
     <skip />
-    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (8168317165722752881) -->
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
     <skip />
-    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (5957064378548718872) -->
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
     <skip />
-    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (9055596817716471373) -->
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
     <skip />
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - প্ৰায় <xliff:g id="TIME">%2$s</xliff:g> বাকী আছে"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - আপোনাৰ ব্যৱহাৰক ভিত্তি কৰি প্ৰায় <xliff:g id="TIME">%2$s</xliff:g> বাকী আছে"</string>
-    <!-- no translation found for power_remaining_duration_shutdown_imminent (7679005631124015335) -->
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
     <skip />
-    <!-- no translation found for power_remaining_duration_shutdown_imminent (261050880878965621) -->
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
     <skip />
-    <!-- no translation found for power_remaining_duration_shutdown_imminent (2020049829798578618) -->
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
     <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"সম্পূৰ্ণকৈ চ্চাৰ্জ হ\'বলৈ <xliff:g id="TIME">%1$s</xliff:g> বাকী"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> সম্পূৰ্ণৰূপে চ্চাৰ্জ হোৱা পৰ্যন্ত"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"অজ্ঞাত"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"চাৰ্জ কৰি থকা হৈছে"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 97e3570..2d235dd 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Şəxsi DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Şəxsi DNS Rejimini Seçin"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Deaktiv"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Geniş imkanlar"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Şəxsi DNS provayderinin host adı"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS provayderinin host adını daxil edin"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Simsiz displey sertifikatlaşması üçün seçimləri göstərir"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Bu funksiya eksperimentaldır və performansa təsir edə bilər."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> tərəfindən qəbul edilmir"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Təxminən <xliff:g id="TIME">%1$s</xliff:g> qalıb"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"İstifadəyə əsasən təxminən <xliff:g id="TIME">%1$s</xliff:g> qalıb"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Tam enerji yığmağına <xliff:g id="TIME">%1$s</xliff:g> qalıb"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> qalıb"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Qalan vaxt <xliff:g id="THRESHOLD">%1$s</xliff:g> və daha azdır"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g> və daha az vaxt qalır"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> - Qalan vaxt <xliff:g id="TIME_REMAINING">%2$s</xliff:g> və daha azdır"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"Qalan vaxt <xliff:g id="TIME_REMAINING">%1$s</xliff:g> və daha çoxdur"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefon tezliklə sönə bilər"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"planşet tezliklə sönə bilər"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"cihaz tezliklə sönə bilər"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - təxminən <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - istifadəyə əsasən təxminən <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - telefon tezliklə sönə bilər"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - planşet tezliklə sönə bilər"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - cihaz tezliklə sönə bilər"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Tam enerji yığmağına <xliff:g id="TIME">%1$s</xliff:g> qalıb"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tam enerji yığana kimi"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Naməlum"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Enerji doldurma"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index dd7043d..1ea7931 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Privatni DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Izaberite režim privatnog DNS-a"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Isključeno"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Opportunistički"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Ime hosta dobavljača usluge privatnog DNS-a"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Unesite ime hosta dobavljača usluge DNS-a"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Prikaz opcija za sertifikaciju bežičnog ekrana"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ova funkcija je eksperimentalna i može da utiče na kvalitet rada."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Zamenjuje ga <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Još oko <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Na osnovu potrošnje imate još otprilike <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> do potpunog punjenja"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Preostalo vreme: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Preostalo je manje od <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – preostalo je manje od <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – preostalo je više od <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"preostalo je više od <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefon će se uskoro isključiti"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet će se uskoro isključiti"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"uređaj će se uskoro isključiti"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – ostalo je oko <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – na osnovu potrošnje imate još otprilike <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – telefon će se uskoro isključiti"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – tablet će se uskoro isključiti"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – uređaj će se uskoro isključiti"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> do potpunog punjenja"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do potpunog punjenja"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Nepoznato"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Punjenje"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 1a0a251..23a785c 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Прыватная DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Выберыце рэжым прыватнай DNS"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Выключана"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Гібкі"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Імя вузла аператара прыватнай DNS"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Увядзіце імя вузла аператара DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Паказаць опцыі сертыфікацыі бесправаднога дысплея"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Гэта функцыя з\'яўляецца эксперыментальнай і можа паўплываць на прадукцыйнасць."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Перавызначаны <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Засталося каля <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Засталося каля <xliff:g id="TIME">%1$s</xliff:g> на аснове вашага выкарыстання"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Да поўнай зарадкі засталося <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Засталося <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Засталося менш за <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – засталося менш за <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – засталося больш за <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"засталося больш за <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"тэлефон у хуткім часе выключыцца"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"планшэт у хуткім часе выключыцца"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"прылада ў хуткім часе выключыцца"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – засталося каля <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – засталося каля <xliff:g id="TIME">%2$s</xliff:g> на аснове вашага выкарыстання"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – тэлефон у хуткім часе выключыцца"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – планшэт у хуткім часе выключыцца"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – прылада ў хуткім часе выключыцца"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Да поўнай зарадкі засталося <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> да поўнай зарадкі"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Невядома"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Зарадка"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index d071c64..5cd345a 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Частен DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Изберете режим на частния DNS"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Изкл."</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"При възможност"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Име на хоста на доставчика на частния DNS"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Въведете името на хоста на DNS доставчика"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Показване на опциите за сертифициране на безжичния дисплей"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Тази функция е експериментална и може да се отрази на ефективността."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Заменено от „<xliff:g id="TITLE">%1$s</xliff:g>“"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Оставащо време: около <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Още около <xliff:g id="TIME">%1$s</xliff:g> въз основа на използването"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Оставащо време до пълно зареждане: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Оставащо време: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Остава/т по-малко от <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – остава/т по-малко от <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – остава/т повече от <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"остава/т повече от <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"възможно е телефонът да се изключи скоро"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"възможно е таблетът да се изключи скоро"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"възможно е устройството да се изключи скоро"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – около <xliff:g id="TIME">%2$s</xliff:g> оставащо време"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – още около <xliff:g id="TIME">%2$s</xliff:g> въз основа на използването"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – възможно е телефонът да се изключи скоро"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – възможно е таблетът да се изключи скоро"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – възможно е устройството да се изключи скоро"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Оставащо време до пълно зареждане: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до пълно зареждане"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Неизвестно"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Зарежда се"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index baa31e6..1e56cf6 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"ব্যক্তিগত ডিএনএস"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"ব্যক্তিগত ডিএনএস মোড বেছে নিন"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"বন্ধ আছে"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"সুবিধাবাদী"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"ব্যক্তিগত ডিএনএস প্রদানকারীর হোস্টনেম"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"ডিএনএস প্রদানকারীর হোস্টনেম লিখুন"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ওয়্যারলেস প্রদর্শন সার্টিফিকেশন জন্য বিকল্পগুলি দেখান"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"এই বৈশিষ্ট্যটি পরীক্ষামূলক এবং এটি কার্য-সম্পাদনা প্রভাবিত করতে পারে।"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> এর দ্বারা ওভাররাইড করা হয়েছে"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"প্রায় <xliff:g id="TIME">%1$s</xliff:g> বাকি"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"বর্তমান ব্যাটারি ব্যবহার অনুযায়ী আর <xliff:g id="TIME">%1$s</xliff:g> বাকি"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"সম্পূর্ণ চার্জ হতে <xliff:g id="TIME">%1$s</xliff:g> বাকি"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> বাকী আছে"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> এর থেকেও কম বাকি আছে"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g> এর থেকেও কম বাকি আছে"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g><xliff:g id="TIME_REMAINING">%2$s</xliff:g> এর থেকে বেশি বাকি আছে"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> এর থেকে বেশি বাকি আছে"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ফোন শীঘ্রই বন্ধ হয়ে যেতে পারে"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ট্যাবলেট শীঘ্রই বন্ধ হয়ে যেতে পারে"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"ডিভাইসটি শীঘ্রই বন্ধ হয়ে যেতে পারে"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - প্রায় <xliff:g id="TIME">%2$s</xliff:g> বাকি আছে"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - বর্তমান ব্যাটারি ব্যবহার অনুযায়ী আর <xliff:g id="TIME">%2$s</xliff:g> বাকি"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - ফোন শীঘ্রই বন্ধ হয়ে যেতে পারে"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - ট্যাবলেট শীঘ্রই বন্ধ হয়ে যেতে পারে"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - ডিভাইসটি শীঘ্রই বন্ধ হয়ে যেতে পারে"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"সম্পূর্ণ চার্জ হতে <xliff:g id="TIME">%1$s</xliff:g> বাকি"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - সম্পূর্ণ চার্জ হতে <xliff:g id="TIME">%2$s</xliff:g> লাগবে"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"অজানা"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"চার্জ হচ্ছে"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index c54a5dc..3c09c9d 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Privatni DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Odaberite način rada privatnog DNS-a"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Isključeno"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Oportunistički"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Naziv host računara privatnog DNS-a"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Unesite naziv host računara pružaoca DNS-a"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Pokaži opcije za certifikaciju Bežičnog prikaza"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ova funkcija je eksperimentalna i može uticati na performanse."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Zamjenjuje <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Preostalo je otprilike još <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Preostalo je još oko <xliff:g id="TIME">%1$s</xliff:g>, na osnovu vašeg korištenja"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Još <xliff:g id="TIME">%1$s</xliff:g> do potpune napunjenosti"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Imate još <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Preostalo je manje od <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – Preostalo je manje od <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>preostalo je više od <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"preostalo je više od <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefon će se uskoro isključiti"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet će se uskoro isključiti"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"uređaj će se uskoro isključiti"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - imate još <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - preostalo je još oko <xliff:g id="TIME">%2$s</xliff:g>, na osnovu vašeg korištenja"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – telefon će se uskoro isključiti"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – tablet će se uskoro isključiti"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – uređaj će se uskoro isključiti"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Još <xliff:g id="TIME">%1$s</xliff:g> do potpune napunjenosti"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> do potpune napunjenosti"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Nepoznato"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Punjenje"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index fc312cf..545dc10 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS privat"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Selecciona el mode de DNS privat"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Desactivat"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Oportunista"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Nom d\'amfitrió del proveïdor de DNS privat"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introdueix el nom d\'amfitrió del proveïdor de DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostra les opcions de certificació de pantalla sense fil"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Aquesta funció és experimental i pot afectar el rendiment."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"S\'ha substituït per <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Temps restant aproximat: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Temps restant aproximat segons l\'ús que en fas: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> per completar la càrrega"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Temps restant: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Queda menys d\'un <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g>: queda menys d\'un <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>: el temps restant és superior a <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"el temps restant és superior a <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"és possible que el telèfon s\'apagui aviat"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"és possible que la tauleta s\'apagui aviat"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"és possible que el dispositiu s\'apagui aviat"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> aproximadament per esgotar la bateria"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g>; temps restant aproximat segons l\'ús que en fas: <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g>: és possible que el telèfon s\'apagui aviat"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g>: és possible que la tauleta s\'apagui aviat"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g>: és possible que el dispositiu s\'apagui aviat"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> per completar la càrrega"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconegut"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"S\'està carregant"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index e6000c1..98455dd 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Soukromé DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Vyberte soukromý režim DNS"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Vypnuto"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Příležitostné"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Název hostitele poskytovatele soukromého DNS"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Zadejte název hostitele poskytovatele DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Zobrazit možnosti certifikace bezdrátového displeje"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Funkce je experimentální a může mít vliv na výkon."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Přepsáno nastavením <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Zbývá asi <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Při vašem obvyklém využití zbývá asi <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Plně se nabije za <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Zbývající čas: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Zbývá méně než <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – zbývá méně než <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – zbývá více než <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"zbývá více než <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefon se brzy vypne"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet se brzy vypne"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"zařízení se brzy vypne"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – zbývá přibližně <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – při vašem obvyklém využití zbývá asi <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – telefon se brzy vypne"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – tablet se brzy vypne"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – zařízení se brzy vypne"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Plně se nabije za <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – plně se nabije za <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Neznámé"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Nabíjí se"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index aa3e6b4..291d4ab 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Privat DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Vælg privat DNS-tilstand"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Fra"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Opportunistisk"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Hostname for privat DNS-udbyder"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Angiv hostname for DNS-udbyder"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Vis valgmuligheder for certificering af trådløs skærm"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Denne funktion er eksperimentel og kan påvirke ydeevnen."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Tilsidesat af <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Ca. <xliff:g id="TIME">%1$s</xliff:g> tilbage"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Der er ca. <xliff:g id="TIME">%1$s</xliff:g> tilbage, alt efter hvordan du bruger enheden"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> til det er fuldt opladet"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> tilbage"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Der er mindre end <xliff:g id="THRESHOLD">%1$s</xliff:g> tilbage"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – der er mindre end <xliff:g id="THRESHOLD">%2$s</xliff:g> tilbage"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – der er mere end <xliff:g id="TIME_REMAINING">%2$s</xliff:g> tilbage"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"der er mere end <xliff:g id="TIME_REMAINING">%1$s</xliff:g> tilbage"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefonen lukker muligvis snart ned"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"denne tablet lukker muligvis snart ned"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"enheden lukker muligvis snart ned"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – ca. <xliff:g id="TIME">%2$s</xliff:g> tilbage"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – der er ca. <xliff:g id="TIME">%2$s</xliff:g> tilbage, alt efter hvordan du bruger enheden"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – telefonen lukker muligvis snart ned"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – denne tablet lukker muligvis snart ned"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – enheden lukker muligvis snart ned"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> til det er fuldt opladet"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> til det er fuldt opladet"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Ukendt"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Oplader"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 5210419..84e33bc 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -56,14 +56,14 @@
     <string name="bluetooth_connected" msgid="5427152882755735944">"Mit <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> verbunden"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"Verbindung wird hergestellt…"</string>
     <string name="bluetooth_connected_no_headset" msgid="616068069034994802">"Mit <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> verbunden (kein Telefon-Audio)"</string>
-    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Mit <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> verbunden (kein Media-Audio)"</string>
+    <string name="bluetooth_connected_no_a2dp" msgid="3736431800395923868">"Mit <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> verbunden (kein Medien-Audio)"</string>
     <string name="bluetooth_connected_no_map" msgid="3200033913678466453">"Mit <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> verbunden (kein Nachrichtenzugriff)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Mit <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> verbunden (weder Telefon- noch Media-Audio)"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2047403011284187056">"Mit <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> verbunden (weder Telefon- noch Medien-Audio)"</string>
     <string name="bluetooth_connected_battery_level" msgid="5162924691231307748">"Mit <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> verbunden, Akkustand bei <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Mit <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> verbunden (kein Telefon-Audio), Akkustand bei <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Mit <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> verbunden (kein Media-Audio), Akkustand bei <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Mit <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> verbunden (weder Telefon- noch Media-Audio), Akkustand bei <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Media-Audio"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Mit <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> verbunden (kein Medien-Audio), Akkustand bei <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Mit <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> verbunden (weder Telefon- noch Medien-Audio), Akkustand bei <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Medien-Audio"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonanrufe"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Dateiübertragung"</string>
     <string name="bluetooth_profile_hid" msgid="3680729023366986480">"Eingabegerät"</string>
@@ -77,8 +77,8 @@
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-Audio"</string>
     <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Hörhilfe"</string>
     <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Mit Hörhilfe verbunden"</string>
-    <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Verbunden mit  Audiosystem von Medien"</string>
-    <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Verbunden mit Audiosystem des Telefons"</string>
+    <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Verbunden mit Medien-Audio"</string>
+    <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Verbunden mit Telefon-Audio"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Mit Dateiübertragungsserver verbunden"</string>
     <string name="bluetooth_map_profile_summary_connected" msgid="8191407438851351713">"Mit Karte verbunden"</string>
     <string name="bluetooth_sap_profile_summary_connected" msgid="8561765057453083838">"Mit SAP verbunden"</string>
@@ -89,8 +89,8 @@
     <string name="bluetooth_pan_profile_summary_use_for" msgid="5736111170225304239">"Für Internetzugriff verwenden"</string>
     <string name="bluetooth_map_profile_summary_use_for" msgid="5154200119919927434">"Für Karte verwenden"</string>
     <string name="bluetooth_sap_profile_summary_use_for" msgid="7085362712786907993">"Für SIM-Zugriff verwenden"</string>
-    <string name="bluetooth_a2dp_profile_summary_use_for" msgid="4630849022250168427">"Für Audiosystem von Medien verwenden"</string>
-    <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Für Audiosystem des Telefons verwenden"</string>
+    <string name="bluetooth_a2dp_profile_summary_use_for" msgid="4630849022250168427">"Für Medien-Audio verwenden"</string>
+    <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Für Telefon-Audio verwenden"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Für Dateiübertragung verwenden"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Für Eingabe verwenden"</string>
     <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Für Hörhilfe verwenden"</string>
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Privates DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Privaten DNS-Modus auswählen"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Aus"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Opportunistisch"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Hostname des privaten DNS-Anbieters"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Hostname des DNS-Anbieters eingeben"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Optionen zur Zertifizierung für kabellose Übertragung anzeigen"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Hierbei handelt es sich um eine experimentelle Funktion, die sich auf die Leistung auswirken kann."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Außer Kraft gesetzt von \"<xliff:g id="TITLE">%1$s</xliff:g>\""</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Ca. <xliff:g id="TIME">%1$s</xliff:g> übrig"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Noch ca. <xliff:g id="TIME">%1$s</xliff:g>, basierend auf deiner Nutzung"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> bis zur vollständigen Aufladung"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Noch <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Weniger als <xliff:g id="THRESHOLD">%1$s</xliff:g> verbleibend"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – weniger als <xliff:g id="THRESHOLD">%2$s</xliff:g> verbleibend"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – mehr als <xliff:g id="TIME_REMAINING">%2$s</xliff:g> verbleibend"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"mehr als <xliff:g id="TIME_REMAINING">%1$s</xliff:g> verbleibend"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"Smartphone wird bald ausgeschaltet"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"Tablet wird bald ausgeschaltet"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"Gerät wird bald ausgeschaltet"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – ungefähr noch <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – noch ca. <xliff:g id="TIME">%2$s</xliff:g>, basierend auf deiner Nutzung"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – Smartphone wird bald ausgeschaltet"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – Tablet wird bald ausgeschaltet"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – Gerät wird bald ausgeschaltet"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> bis zur vollständigen Aufladung"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> bis vollständig geladen"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Unbekannt"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Wird aufgeladen"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index fe1c6bc..55b0171 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Ιδιωτικό DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Επιλέξτε τη λειτουργία ιδιωτικού DNS"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Ανενεργή"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Καιροσκοπική"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Όνομα κεντρικού υπολογιστή παρόχου DNS"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Εισαγάγετε το όνομα κεντρικού υπολογιστή του παρόχου DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Εμφάνιση επιλογών για πιστοποίηση ασύρματης οθόνης"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Αυτή η λειτουργία είναι πειραματική και ενδεχομένως να επηρεάσει τις επιδόσεις."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Αντικαταστάθηκε από <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Απομένουν περίπου <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Απομένει/ουν περίπου <xliff:g id="TIME">%1$s</xliff:g> με βάση τη χρήση σας"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Απομένουν <xliff:g id="TIME">%1$s</xliff:g> έως την πλήρη φόρτιση"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Απομένει/ουν <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Απομένει/ουν λιγότερo/α από <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Απομένει λιγότερo από <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> - Απομένει περισσότερο από <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"απομένουν περισσότερα/ες από <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"το τηλέφωνο μπορεί να απενεργοποιηθεί σύντομα"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"το tablet μπορεί να απενεργοποιηθεί σύντομα"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"η συσκευή μπορεί να απενεργοποιηθεί σύντομα"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - απομένουν περίπου <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Απομένει/ουν περίπου <xliff:g id="TIME">%2$s</xliff:g> με βάση τη χρήση σας"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - το τηλέφωνο μπορεί να απενεργοποιηθεί σύντομα"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - το tablet μπορεί να απενεργοποιηθεί σύντομα"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - η συσκευή μπορεί να απενεργοποιηθεί σύντομα"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Απομένουν <xliff:g id="TIME">%1$s</xliff:g> έως την πλήρη φόρτιση"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> για πλήρη φόρτιση"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Άγνωστο"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Φόρτιση"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 5b8adcf..8ff83b0 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Private DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Select private DNS mode"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Off"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Opportunistic"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Private DNS provider hostname"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Enter hostname of DNS provider"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Show options for wireless display certification"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"This feature is experimental and may affect performance."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"About <xliff:g id="TIME">%1$s</xliff:g> left"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"About <xliff:g id="TIME">%1$s</xliff:g> left based on your usage"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> left until fully charged"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> left"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Less than <xliff:g id="THRESHOLD">%2$s</xliff:g> remaining"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>more than <xliff:g id="TIME_REMAINING">%2$s</xliff:g> remaining"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"more than <xliff:g id="TIME_REMAINING">%1$s</xliff:g> remaining"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"phone may shutdown soon"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet may shutdown soon"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"device may shutdown soon"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – about <xliff:g id="TIME">%2$s</xliff:g> left"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - about <xliff:g id="TIME">%2$s</xliff:g> left based on your usage"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - phone may shutdown soon"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - tablet may shutdown soon"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - device may shutdown soon"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> left until fully charged"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> until fully charged"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 5b8adcf..8ff83b0 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Private DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Select private DNS mode"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Off"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Opportunistic"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Private DNS provider hostname"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Enter hostname of DNS provider"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Show options for wireless display certification"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"This feature is experimental and may affect performance."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"About <xliff:g id="TIME">%1$s</xliff:g> left"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"About <xliff:g id="TIME">%1$s</xliff:g> left based on your usage"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> left until fully charged"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> left"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Less than <xliff:g id="THRESHOLD">%2$s</xliff:g> remaining"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>more than <xliff:g id="TIME_REMAINING">%2$s</xliff:g> remaining"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"more than <xliff:g id="TIME_REMAINING">%1$s</xliff:g> remaining"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"phone may shutdown soon"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet may shutdown soon"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"device may shutdown soon"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – about <xliff:g id="TIME">%2$s</xliff:g> left"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - about <xliff:g id="TIME">%2$s</xliff:g> left based on your usage"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - phone may shutdown soon"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - tablet may shutdown soon"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - device may shutdown soon"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> left until fully charged"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> until fully charged"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 5b8adcf..8ff83b0 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Private DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Select private DNS mode"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Off"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Opportunistic"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Private DNS provider hostname"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Enter hostname of DNS provider"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Show options for wireless display certification"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"This feature is experimental and may affect performance."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"About <xliff:g id="TIME">%1$s</xliff:g> left"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"About <xliff:g id="TIME">%1$s</xliff:g> left based on your usage"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> left until fully charged"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> left"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Less than <xliff:g id="THRESHOLD">%2$s</xliff:g> remaining"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>more than <xliff:g id="TIME_REMAINING">%2$s</xliff:g> remaining"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"more than <xliff:g id="TIME_REMAINING">%1$s</xliff:g> remaining"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"phone may shutdown soon"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet may shutdown soon"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"device may shutdown soon"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – about <xliff:g id="TIME">%2$s</xliff:g> left"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - about <xliff:g id="TIME">%2$s</xliff:g> left based on your usage"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - phone may shutdown soon"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - tablet may shutdown soon"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - device may shutdown soon"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> left until fully charged"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> until fully charged"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 5b8adcf..8ff83b0 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Private DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Select private DNS mode"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Off"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Opportunistic"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Private DNS provider hostname"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Enter hostname of DNS provider"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Show options for wireless display certification"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"This feature is experimental and may affect performance."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"About <xliff:g id="TIME">%1$s</xliff:g> left"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"About <xliff:g id="TIME">%1$s</xliff:g> left based on your usage"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> left until fully charged"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> left"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Less than <xliff:g id="THRESHOLD">%2$s</xliff:g> remaining"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>more than <xliff:g id="TIME_REMAINING">%2$s</xliff:g> remaining"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"more than <xliff:g id="TIME_REMAINING">%1$s</xliff:g> remaining"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"phone may shutdown soon"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet may shutdown soon"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"device may shutdown soon"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – about <xliff:g id="TIME">%2$s</xliff:g> left"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - about <xliff:g id="TIME">%2$s</xliff:g> left based on your usage"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - phone may shutdown soon"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - tablet may shutdown soon"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - device may shutdown soon"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> left until fully charged"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> until fully charged"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index b7ca84a..56e97e4 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‏‏‎‏‎‏‎‏‎‏‎‎‏‏‎‏‎‎‎‏‎‏‎‎‎‎‏‎‎‎‎‏‎‎‏‏‏‏‎‎‎‏‎‏‏‎‎‏‏‎‎‏‎‎Private DNS‎‏‎‎‏‎"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‎‏‎‏‏‎‏‏‏‎‏‎‏‏‎‎‏‏‏‏‏‎‏‏‎Select Private DNS Mode‎‏‎‎‏‎"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‏‏‎‎‎‏‏‎‎‎‏‎‏‏‏‏‏‏‎‎‏‎‏‏‏‎‏‏‏‏‎‏‏‎‏‏‏‎‎‏‏‎‎‏‎‎‏‎‏‎‎‎Off‎‏‎‎‏‎"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‎‏‏‎‏‎‎‎‎‎‎‎‎‏‎‏‎‏‏‏‏‏‏‎‏‎‏‏‎‏‏‎‏‎‎‏‏‏‏‏‎‏‎‏‏‏‏‏‎‏‏‎‎Opportunistic‎‏‎‎‏‎"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‎‎‏‎‏‎‎‎‎‏‏‎‎‏‎‎‎‏‏‎‏‎‏‎‏‎‎‏‎‎‎‏‏‏‏‎‎‏‎‎‏‎‎‎Private DNS provider hostname‎‏‎‎‏‎"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‎‏‎‎‎‎‏‎‏‎‏‎‏‏‎‎‏‎‎‏‎‎‏‎‏‏‎‎‎‏‎‏‎‏‏‏‎‎‏‎‎‎‎‎‎‎‏‎‎‎‎‎‎‏‏‏‏‎Enter hostname of DNS provider‎‏‎‎‏‎"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‎‎‎‎‎‏‎‎‎‎‎‎‎‏‎‎‎‎‎‏‏‎‎‎‎‏‎‎‏‎‏‎‎‏‎‏‏‎‎‏‏‎‎‎‎‏‏‎‏‎‏‎‏‏‏‎‏‎Show options for wireless display certification‎‏‎‎‏‎"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‎‎‎‎‏‎‏‏‏‎‏‎‎‎‏‏‎‎‎‏‏‎‏‏‎‏‎‏‏‏‏‎‎‎‏‏‏‏‎‏‎‏‏‎‎‎‎‏‏‏‎‏‏‎‏‏‏‏‏‎This feature is experimental and may affect performance.‎‏‎‎‏‎"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‏‏‎‏‎‎‎‎‎‏‏‎‎‏‏‏‏‏‎‎‎‎‎‎‎‏‎‎‏‎‎‏‏‎‏‎‏‏‎‏‎‎‏‎‎‏‎‎‏‏‎‎‎‏‏‏‎‎‎Overridden by ‎‏‎‎‏‏‎<xliff:g id="TITLE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‏‏‎‏‏‏‎‏‏‏‎‎‏‎‎‏‏‎‎‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‎‎‎‎‏‏‎‏‏‎‏‏‎‏‏‎‏‎‏‎‎‏‎‎About ‎‏‎‎‏‏‎<xliff:g id="TIME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ left‎‏‎‎‏‎"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‎‏‎‎‏‎‏‏‏‏‎‏‏‏‎‏‎‎‎‏‏‏‏‎‎‏‏‏‏‎‎‎‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎‏‎‏‏‏‎‎About ‎‏‎‎‏‏‎<xliff:g id="TIME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ left based on your usage‎‏‎‎‏‎"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‏‎‎‎‏‏‎‎‎‏‎‏‎‎‏‎‎‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‏‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="TIME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ left until fully charged‎‏‎‎‏‎"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‎‎‏‎‏‎‏‏‏‏‎‎‏‏‏‎‏‏‎‏‎‏‎‎‎‎‏‎‏‏‏‎‎‏‏‏‏‎‏‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="TIME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ left‎‏‎‎‏‎"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‏‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‎‏‎‎‎‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‎‏‏‎‎‏‏‎‏‏‏‎‎‎‎‏‎Less than ‎‏‎‎‏‏‎<xliff:g id="THRESHOLD">%1$s</xliff:g>‎‏‎‎‏‏‏‎ remaining‎‏‎‎‏‎"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‎‏‏‎‎‎‎‎‎‎‏‎‎‏‏‎‎‏‏‏‏‏‎‎‏‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - Less than ‎‏‎‎‏‏‎<xliff:g id="THRESHOLD">%2$s</xliff:g>‎‏‎‎‏‏‏‎ remaining‎‏‎‎‏‎"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‎‎‏‎‎‎‏‏‎‏‏‎‎‎‏‏‏‏‎‏‏‎‎‏‏‎‏‏‏‎‏‎‏‏‏‏‏‎‎‎‏‎‏‏‎‎‏‏‏‏‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎more than ‎‏‎‎‏‏‎<xliff:g id="TIME_REMAINING">%2$s</xliff:g>‎‏‎‎‏‏‏‎ remaining‎‏‎‎‏‎"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‏‎‎‎‎‎‎‏‎‏‏‎‏‏‎‎‏‏‎‏‎‏‎‎‏‏‎‎‎‎‎‎‏‏‏‎‎‎‎‎‏‏‏‎‏‎‏‎‎‏‎‎more than ‎‏‎‎‏‏‎<xliff:g id="TIME_REMAINING">%1$s</xliff:g>‎‏‎‎‏‏‏‎ remaining‎‏‎‎‏‎"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‏‎‏‏‏‎‏‏‎‎‎‏‎‎‏‎‏‏‏‏‎‏‎‎‎‎‏‏‏‎‏‎‎‎‎‏‎‏‎‏‎‏‏‏‎‏‏‏‎‎‎‏‎phone may shutdown soon‎‏‎‎‏‎"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‏‎‏‎‏‏‏‎‏‏‏‏‏‎‎‏‏‏‏‏‎‏‏‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‏‎‎‎‏‏‎‏‎‎‎‏‏‎‎‎‎tablet may shutdown soon‎‏‎‎‏‎"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‎‏‏‏‎‏‏‏‏‎‏‎‎‏‎‎‏‎‏‏‏‏‎‎‏‏‎‎‏‎‎‏‏‎‏‎device may shutdown soon‎‏‎‎‏‎"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‏‎‏‏‏‎‏‏‏‎‎‎‎‎‏‎‎‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‎‏‏‎‎‏‏‎‎‎‏‏‎‎‏‎‎‎‏‎‏‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - about ‎‏‎‎‏‏‎<xliff:g id="TIME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ left‎‏‎‎‏‎"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‎‏‎‎‎‏‎‏‏‎‎‏‎‎‎‏‎‏‏‎‎‎‎‎‏‏‏‎‏‏‎‏‎‎‎‏‎‏‏‏‎‎‏‏‎‏‏‎‏‎‏‏‎‎‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - about ‎‏‎‎‏‏‎<xliff:g id="TIME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ left based on your usage‎‏‎‎‏‎"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‎‎‎‏‎‏‎‎‏‏‏‎‏‏‏‎‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‏‏‏‏‏‎‎‎‎‏‎‎‎‏‏‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - phone may shutdown soon‎‏‎‎‏‎"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‏‏‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‏‎‎‏‎‎‏‎‎‏‏‏‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‎‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - tablet may shutdown soon‎‏‎‎‏‎"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‎‎‎‎‎‎‏‎‎‎‏‎‏‎‏‎‎‎‏‎‎‏‏‏‏‎‎‎‎‏‎‏‎‏‏‎‏‏‏‎‏‏‏‎‎‎‏‎‎‏‏‎‏‏‏‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - device may shutdown soon‎‏‎‎‏‎"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‎‎‏‎‏‏‎‎‏‎‎‎‏‎‏‎‏‏‎‏‏‎‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‏‏‎‏‏‎‏‏‏‏‎‎‎‏‏‎‎‏‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - ‎‏‎‎‏‏‎<xliff:g id="STATE">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‏‎‎‎‏‏‎‎‎‏‎‏‎‎‏‎‎‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‏‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="TIME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ left until fully charged‎‏‎‎‏‎"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‎‏‎‎‎‎‎‎‎‏‎‏‎‏‎‏‏‎‎‏‏‏‏‏‏‎‎‎‎‎‏‏‎‏‏‎‏‏‏‎‎‏‏‏‎‎‎‏‎‎‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - ‎‏‎‎‏‏‎<xliff:g id="TIME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ until fully charged‎‏‎‎‏‎"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‎‏‎‏‏‏‎‎‎‏‏‎‎‏‎‏‏‏‎‏‏‏‏‏‎‎‎‎‎‏‏‏‎‎‏‏‏‏‏‏‏‎‎‏‏‎‎‏‏‎‎‏‏‎‎‏‏‎Unknown‎‏‎‎‏‎"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‏‏‏‎‏‎‏‎‏‎‎‎‎‎‎‏‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‎‏‏‏‎‎‎‏‎‏‎‏‏‎‏‏‏‏‏‏‎‏‎‎‏‎‎‎Charging‎‏‎‎‏‎"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index bf62e59..bdff9a0 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS privado"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Selecciona el modo de DNS privado"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Desactivado"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Oportunista"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Nombre de host del proveedor de DNS privado"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Ingresa el nombre de host del proveedor de DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opciones de certificación de pantalla inalámbrica"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta función es experimental y puede afectar el rendimiento."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Reemplazado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Tiempo restante aproximado: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Aproximadamente <xliff:g id="TIME">%1$s</xliff:g> restantes en función del uso"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> para completar la carga"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Tiempo restante: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Tiempo restante: menos de <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> (tiempo restante: menos de <xliff:g id="THRESHOLD">%2$s</xliff:g>)"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> (tiempo restante: más de <xliff:g id="TIME_REMAINING">%2$s</xliff:g>)"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"Tiempo restante: más de <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"es posible que pronto se apague el teléfono"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"es posible que pronto se apague la tablet"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"es posible que pronto se apague el dispositivo"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> (tiempo restante: <xliff:g id="TIME">%2$s</xliff:g>)"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> (aproximadamente <xliff:g id="TIME">%2$s</xliff:g> restantes en función del uso)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g>: es posible que pronto se apague el teléfono"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g>: es posible que pronto se apague la tablet"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g>: es posible que pronto se apague el dispositivo"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> para completar la carga"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> (<xliff:g id="TIME">%2$s</xliff:g> para completar la carga)"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconocido"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Cargando"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 5a9b873..940c84f 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS privado"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Selecciona el modo de DNS privado"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"No"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Oportunista"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Nombre de host de proveedor de DNS privado"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introduce el nombre de host del proveedor de DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opciones para la certificación de la pantalla inalámbrica"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta función es experimental y puede afectar al rendimiento."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Anulado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Tiempo restante aproximado: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Tiempo restante aproximado según tu uso: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Tiempo restante hasta carga completa: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Tiempo restante: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Tiempo restante: menos de <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> (tiempo restante: menos de <xliff:g id="THRESHOLD">%2$s</xliff:g>)"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> (tiempo restante: más de <xliff:g id="TIME_REMAINING">%2$s</xliff:g>)"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"Tiempo restante: más de <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"es posible que el teléfono se apague pronto"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"es posible que el tablet se apague pronto"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"es posible que el dispositivo se apague pronto"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - tiempo aproximado restante: <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> (tiempo restante aproximado según tu uso: <xliff:g id="TIME">%2$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g>: es posible que el teléfono se apague pronto"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g>: es posible que el tablet se apague pronto"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g>: es posible que el dispositivo se apague pronto"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Tiempo restante hasta carga completa: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar la carga"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconocido"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Cargando"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 77d55ff..a53b894 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Privaatne DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Valige privaatse DNS-i režiim"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Väljas"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Oportunistlik"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Privaatse DNS-i teenusepakkuja hostinimi"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Sisestage DNS-i teenusepakkuja hostinimi"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Juhtmeta ekraaniühenduse sertifitseerimisvalikute kuvamine"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"See funktsioon on katseline ja võib mõjutada toimivust."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Alistas <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Umbes <xliff:g id="TIME">%1$s</xliff:g> on jäänud"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Teie kasutuse alusel on jäänud ligikaudu <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> täislaadimiseni"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> on jäänud"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Jäänud on alla <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – jäänud on alla <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>jäänud on üle <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"jäänud on üle <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefon võib peagi välja lülituda"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tahvelarvuti võib peagi välja lülituda"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"seade võib peagi välja lülituda"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – umbes <xliff:g id="TIME">%2$s</xliff:g> on jäänud"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – teie kasutuse alusel on jäänud ligikaudu <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – telefon võib peagi välja lülituda"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – tahvelarvuti võib peagi välja lülituda"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – seade võib peagi välja lülituda"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> täislaadimiseni"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> täislaadimiseni"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Tundmatu"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Laadimine"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 7da1e76..bcaf79c 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -200,7 +200,7 @@
     <string name="wifi_display_certification" msgid="8611569543791307533">"Hari gabeko bistaratze-egiaztatzea"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Gaitu Wi-Fi sareetan saioa hasteko modu xehatua"</string>
     <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Konektatutako MAC helbideak ausaz aukeratzea"</string>
-    <string name="mobile_data_always_on" msgid="8774857027458200434">"Datu mugikorrak beti aktibo"</string>
+    <string name="mobile_data_always_on" msgid="8774857027458200434">"Datu-konexioa beti aktibo"</string>
     <string name="tethering_hardware_offload" msgid="7470077827090325814">"Konexioa partekatzeko hardwarearen azelerazioa"</string>
     <string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Erakutsi Bluetooth gailuak izenik gabe"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desgaitu bolumen absolutua"</string>
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS pribatua"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Hautatu DNS pribatuaren modua"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Desaktibatuta"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Ahal bada"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"DNS hornitzaile pribatuaren ostalari-izena"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Idatzi DNS hornitzailearen ostalari-izena"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Erakutsi hari gabeko bistaratze-egiaztapenaren aukerak"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Eginbidea esperimentala da eta eragina izan dezake funtzionamenduan."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> hobespena gainjarri zaio"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"<xliff:g id="TIME">%1$s</xliff:g> inguru gelditzen dira"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"<xliff:g id="TIME">%1$s</xliff:g> inguru gelditzen dira, erabileraren arabera"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> falta dira guztiz kargatu arte"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> guztiz kargatu arte"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> baino gutxiago gelditzen dira"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="THRESHOLD">%2$s</xliff:g> baino gutxiago gelditzen dira"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME_REMAINING">%2$s</xliff:g> baino gehiago gelditzen dira"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> baino gehiago gelditzen dira"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"baliteke telefonoa laster itzaltzea"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"baliteke tableta laster itzaltzea"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"baliteke gailua laster itzaltzea"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> inguru gelditzen dira"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> inguru gelditzen dira, erabileraren arabera"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g>: baliteke telefonoa laster itzaltzea"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g>: baliteke tableta laster itzaltzea"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g>: baliteke gailua laster itzaltzea"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> falta dira guztiz kargatu arte"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> guztiz kargatu arte"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Ezezaguna"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Kargatzen"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 2e5d699..14e942d 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"‏DNS خصوصی"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"‏حالت DNS خصوصی را انتخاب کنید"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"خاموش"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"فرصت‌طلب"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"‏نام میزبان ارائه‌دهنده DNS خصوصی"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"‏نام میزبان ارائه‌دهنده DNS خصوصی را وارد کنید"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"نمایش گزینه‌ها برای گواهینامه نمایش بی‌سیم"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"این قابلیت آزمایشی است و ممکن است عملکرد را تحت تأثیر قرار دهد."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"توسط <xliff:g id="TITLE">%1$s</xliff:g> لغو شد"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"حدود <xliff:g id="TIME">%1$s</xliff:g> باقی مانده است"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"براساس میزان مصرف شما، <xliff:g id="TIME">%1$s</xliff:g> باقی‌مانده است"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> تا شارژ شدن کامل باقی مانده است"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> باقی مانده"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"کمتر از <xliff:g id="THRESHOLD">%1$s</xliff:g> باقی مانده"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - کمتر از <xliff:g id="THRESHOLD">%2$s</xliff:g> باقی مانده"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>بیشتر از <xliff:g id="TIME_REMAINING">%2$s</xliff:g> باقی مانده"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"بیشتر از <xliff:g id="TIME_REMAINING">%1$s</xliff:g> باقی مانده"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ممکن است تلفن به‌زودی خاموش شود"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ممکن است رایانه لوحی به‌زودی خاموش شود"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"ممکن است دستگاه به‌زودی خاموش شود"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - تقریباً <xliff:g id="TIME">%2$s</xliff:g> باقی مانده است"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - براساس میزان مصرف شما، <xliff:g id="TIME">%2$s</xliff:g> باقی‌مانده است"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - ممکن است تلفن به‌زودی خاموش شود"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - ممکن است رایانه لوحی به‌زودی خاموش شود"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - ممکن است دستگاه به‌زودی خاموش شود"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - ‏<xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> تا شارژ شدن کامل باقی مانده است"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> مانده تا شارژ کامل"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"ناشناس"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"در حال شارژ شدن"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 28d14a5..040a475 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Yksityinen DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Valitse yksityinen DNS-tila"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Pois käytöstä"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Opportunistinen"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Yksityisen DNS-tarjoajan isäntänimi"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Anna isäntänimi tai DNS-tarjoaja."</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Näytä langattoman näytön sertifiointiin liittyvät asetukset"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Tämä ominaisuus on kokeellinen ja voi vaikuttaa suorituskykyyn."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Tämän ohittaa <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Noin <xliff:g id="TIME">%1$s</xliff:g> jäljellä"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Noin <xliff:g id="TIME">%1$s</xliff:g> jäljellä käytön perusteella"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> kunnes täynnä"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> jäljellä"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Alle <xliff:g id="THRESHOLD">%1$s</xliff:g> jäljellä"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – Alle <xliff:g id="THRESHOLD">%2$s</xliff:g> jäljellä"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> yli <xliff:g id="TIME_REMAINING">%2$s</xliff:g> jäljellä"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"yli <xliff:g id="TIME_REMAINING">%1$s</xliff:g> jäljellä"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"puhelin voi pian sammua"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tabletti voi pian sammua"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"laite voi pian sammua"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – noin <xliff:g id="TIME">%2$s</xliff:g> jäljellä"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – noin <xliff:g id="TIME">%2$s</xliff:g> jäljellä käytön perusteella"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – puhelin voi pian sammua"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – tabletti voi pian sammua"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – laite voi pian sammua"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> kunnes täynnä"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> täyteen lataukseen"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Tuntematon"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Ladataan"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index ed6581d..2e9caa6 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS privé"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Sélectionnez le mode DNS privé"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Désactivé"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Opportuniste"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Nom d\'hôte du fournisseur DNS privé"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Entrez le nom d\'hôte du fournisseur DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Afficher les options pour la certification d\'affichage sans fil"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Cette fonctionnalité est expérimentale et peut affecter les performances."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Remplacé par <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Il reste environ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Il reste environ <xliff:g id="TIME">%1$s</xliff:g> en fonction de votre usage"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> jusqu\'à la charge complète"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Temps restant : <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Il reste moins de <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> : il reste moins de <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> : il reste plus de <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"il reste plus de <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"il se peut que le téléphone s\'éteigne bientôt"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"il se peut que la tablette s\'éteigne bientôt"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"il se peut que l\'appareil s\'éteigne bientôt"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> : il reste environ <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> : il reste environ <xliff:g id="TIME">%2$s</xliff:g> en fonction de votre usage"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> : il se peut que le téléphone s\'éteigne bientôt"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g>: il se peut que la tablette s\'éteigne bientôt"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> : il se peut que l\'appareil s\'éteigne bientôt"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> jusqu\'à la charge complète"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> : <xliff:g id="TIME">%2$s</xliff:g> jusqu\'à la charge complète"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Inconnu"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Charge en cours…"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 39d7aec..8225c4d 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS privé"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Sélectionner le mode DNS privé"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Désactivé"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Opportuniste"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Nom d\'hôte du fournisseur DNS privé"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Saisissez le nom d\'hôte du fournisseur DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Afficher les options de la certification de l\'affichage sans fil"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Cette fonctionnalité est expérimentale et peut affecter les performances."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Remplacé par <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Il reste environ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Temps restant en fonction de votre utilisation : environ <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> avant charge complète"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Temps restant : <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Il reste moins de <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – Il reste moins de <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – Il reste plus de <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"Il reste plus de <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"Il est possible que le téléphone s\'éteigne bientôt"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"Il est possible que la tablette s\'éteigne bientôt"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"Il est possible que l\'appareil s\'éteigne bientôt"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - encore environ <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – Temps restant en fonction de votre utilisation : environ <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – Il est possible que le téléphone s\'éteigne bientôt"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – Il est possible que la tablette s\'éteigne bientôt"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – Il est possible que l\'appareil s\'éteigne bientôt"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> avant charge complète"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> jusqu\'à la charge complète"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Inconnu"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Batterie en charge"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index effcd47..839a25e 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -93,7 +93,7 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Utilízase para o audio do teléfono"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Utilízase para a transferencia de ficheiros"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Utilízase para a entrada"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Usar para o audiófono"</string>
+    <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Usar para os audiófonos"</string>
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Sincronizar"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SINCRONIZAR"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancelar"</string>
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS privado"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Selecciona o modo de DNS privado"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Desactivar"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Oportunista"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Nome de host de provedor de DNS privado"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introduce o nome de host de provedor de DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostra opcións para o certificado de visualización sen fíos"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta función é experimental e pode afectar ao rendemento."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Anulado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Tempo que queda aproximadamente: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Tempo restante aproximado en función do uso: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Tempo que queda ata cargar de todo: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Tempo restante: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Tempo restante inferior a <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g>: tempo restante inferior a <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>: tempo restante superior a <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"tempo restante superior a: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"é posible que o teléfono se apague en breve"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"é posible que a tableta se apague en breve"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"é posible que o dispositivo se apague en breve"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> (tempo restante aproximado: <xliff:g id="TIME">%2$s</xliff:g>)"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tempo restante aproximado en función do uso: <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g>: é posible que o teléfono se apague en breve"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g>: é posible que a tableta se apague en breve"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g>: é posible que o dispositivo se apague en breve"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Tempo que queda ata cargar de todo: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ata completar a carga"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Descoñecido"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Cargando"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index c517b8b..9b54fa6 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"ખાનગી DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"ખાનગી DNS મોડને પસંદ કરો"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"બંધ"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"તકવાદી"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"ખાનગી DNS પ્રદાતા હોસ્ટનું નામ"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS પ્રદાતાના હોસ્ટનું નામ દાખલ કરો"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"વાયરલેસ ડિસ્પ્લે પ્રમાણપત્ર માટેના વિકલ્પો બતાવો"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"આ સુવિધા પ્રાયોગિક છે અને કામગીરી પર અસર કરી શકે છે."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> દ્વારા ઓવરરાઇડ થયું"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"અંદાજે <xliff:g id="TIME">%1$s</xliff:g> બાકી"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"તમારા વપરાશનાં આધારે લગભગ <xliff:g id="TIME">%1$s</xliff:g> બાકી છે"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"સંપૂર્ણપણે ચાર્જ થવામાં <xliff:g id="TIME">%1$s</xliff:g> બાકી"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> બાકી"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> કરતાં ઓછો સમય બાકી છે"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g> કરતાં ઓછો સમય બાકી છે"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g><xliff:g id="TIME_REMAINING">%2$s</xliff:g> કરતાં વધુ સમય બાકી છે"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> કરતાં વધુ સમય બાકી છે"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ફોન થોડી વારમાં બંધ થઈ શકે છે"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ટૅબ્લેટ થોડી વારમાં બંધ થઈ શકે છે"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"ઉપકરણ થોડી વારમાં બંધ થઈ શકે છે"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - લગભગ <xliff:g id="TIME">%2$s</xliff:g> બાકી"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - તમારા વપરાશનાં આધારે લગભગ <xliff:g id="TIME">%2$s</xliff:g> બાકી છે"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - ફોન થોડી વારમાં બંધ થઈ શકે છે"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - ટૅબ્લેટ થોડી વારમાં બંધ થઈ શકે છે"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - ઉપકરણ થોડી વારમાં બંધ થઈ શકે છે"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"સંપૂર્ણપણે ચાર્જ થવામાં <xliff:g id="TIME">%1$s</xliff:g> બાકી"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - સંપૂર્ણપણે ચાર્જ થવા માટે <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"અજાણ્યું"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"ચાર્જ થઈ રહ્યું છે"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 2726c46..9179f2e 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"निजी DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"निजी DNS मोड चुनें"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"बंद"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"मौका मिलते ही काम करने वाला"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"निजी DNS सेवा देने वाले का होस्टनाम"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS सेवा देने वाले का होस्टनाम डालें"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"वायरलेस दिखाई देने के लिए प्रमाणन विकल्प दिखाएं"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"यह सुविधा प्रायोगिक है और निष्पादन को प्रभावित कर सकती है."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> के द्वारा ओवरराइड किया गया"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"लगभग <xliff:g id="TIME">%1$s</xliff:g> शेष"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"आपके उपयोग के आधार पर लगभग <xliff:g id="TIME">%1$s</xliff:g> का समय बचा है"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"पूरी तरह से चार्ज होने में <xliff:g id="TIME">%1$s</xliff:g> शेष"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> शेष"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> से कम समय बचा है"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g> से कम बैटरी बची है"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> <xliff:g id="TIME_REMAINING">%2$s</xliff:g> से ज़्यादा बैटरी बची है"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> से ज़्यादा बैटरी बची है"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"फ़ोन जल्दी ही बंद हो सकता है"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"टैबलेट जल्दी ही बंद हो सकता है"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"डिवाइस जल्दी ही बंद हो सकता है"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - लगभग <xliff:g id="TIME">%2$s</xliff:g> शेष"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - आपके उपयोग के आधार पर लगभग <xliff:g id="TIME">%2$s</xliff:g> का समय बचा है"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - फ़ोन जल्दी ही बंद हो सकता है"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - टैबलेट जल्दी ही बंद हो सकता है"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - डिवाइस जल्दी ही बंद हो सकता है"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"पूरी तरह से चार्ज होने में <xliff:g id="TIME">%1$s</xliff:g> शेष"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> पूरी तरह से चार्ज होने तक"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"अज्ञात"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"चार्ज हो रही है"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index f7d59f0..f0a7fc4 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Privatni DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Odaberite način privatnog DNS-a"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Isključeno"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Oportunistički"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Naziv hosta davatelja usluge privatnog DNS-a"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Unesite naziv hosta davatelja usluge DNS-a"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Prikaži opcije za certifikaciju bežičnog prikaza"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ova je značajka eksperimentalna i može utjecati na performanse."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Premošćeno postavkom <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Još otprilike <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Još otprilike <xliff:g id="TIME">%1$s</xliff:g> na temelju vaše upotrebe"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Još <xliff:g id="TIME">%1$s</xliff:g> do potpune napunjenosti"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Još <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Preostalo je manje od <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – preostalo je manje od <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – preostalo je više od <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"preostalo je više od <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefon bi se uskoro mogao isključiti"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet bi se uskoro mogao isključiti"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"uređaj bi se uskoro mogao isključiti"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – preostalo je približno <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – još otprilike <xliff:g id="TIME">%2$s</xliff:g> na temelju vaše upotrebe"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – telefon bi se uskoro mogao isključiti"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – tablet bi se uskoro mogao isključiti"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – uređaj bi se uskoro mogao isključiti"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Još <xliff:g id="TIME">%1$s</xliff:g> do potpune napunjenosti"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do potpune napunjenosti"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Nepoznato"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Punjenje"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 35a5560..b354ea9 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Privát DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"„Privát DNS” mód kiválasztása"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Ki"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Opportunista"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Privát DNS-szolgáltató gazdagépneve"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Adja meg a DNS-szolgáltató gazdagépnevét"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Vezeték nélküli kijelző tanúsítványával kapcsolatos lehetőségek megjelenítése"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ez egy kísérleti funkció, és hatással lehet a teljesítményre."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Felülírva erre: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Körülbelül <xliff:g id="TIME">%1$s</xliff:g> maradt hátra"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Körülbelül <xliff:g id="TIME">%1$s</xliff:g> van hátra az eszköz igénybevétele alapján"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> a teljes töltöttségig"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> van hátra"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Kevesebb mint <xliff:g id="THRESHOLD">%1$s</xliff:g> van hátra"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – kevesebb mint <xliff:g id="THRESHOLD">%2$s</xliff:g> van hátra"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – több mint <xliff:g id="TIME_REMAINING">%2$s</xliff:g> van hátra"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"több mint <xliff:g id="TIME_REMAINING">%1$s</xliff:g> van hátra"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"előfordulhat, hogy a telefon hamarosan leáll"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"előfordulhat, hogy a táblagép hamarosan leáll"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"előfordulhat, hogy az eszköz hamarosan leáll"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - körülbelül <xliff:g id="TIME">%2$s</xliff:g> van hátra"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – körülbelül <xliff:g id="TIME">%2$s</xliff:g> van hátra az eszköz igénybevétele alapján"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – előfordulhat, hogy a telefon hamarosan leáll"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – előfordulhat, hogy a táblagép hamarosan leáll"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – előfordulhat, hogy az eszköz hamarosan leáll"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> a teljes töltöttségig"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> a teljes feltöltésig"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Ismeretlen"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Töltés"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 44a1714..8e52ceb 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Անհատական DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Ընտրեք անհատական DNS սերվերի ռեժիմը"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Անջատված է"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Ճկուն"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Անհատական DNS ծառայության մատակարարի խնամորդի անունը"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Մուտքագրեք DNS ծառայության մատակարարի խնամորդի անունը"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Ցույց տալ անլար էկրանի հավաստագրման ընտրանքները"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Սա փորձնական գործառույթ է և կարող է ազդել սարքի աշխատանքի վրա:"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Գերազանցված է <xliff:g id="TITLE">%1$s</xliff:g>-ից"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Մնացել է մոտ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Մնացել է մոտ <xliff:g id="TIME">%1$s</xliff:g>՝ օգտագործման եղանակից կախված"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Մինչև լրիվ լիցքավորումը մնացել է <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Մնացել է <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Մնացել է <xliff:g id="THRESHOLD">%1$s</xliff:g>-ից պակաս"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g>՝ մնացել է <xliff:g id="THRESHOLD">%2$s</xliff:g>-ից պակաս"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>՝ մնացել է ավելի քան <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"մնացել է ավելի քան <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"հնարավոր է հեռախոսը շուտով կանջատվի"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"հնարավոր է պլանշետը շուտով կանջատվի"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"հնարավոր է սարքը շուտով կանջատվի"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – մնացել է մոտ <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - մնացել է մոտ <xliff:g id="TIME">%2$s</xliff:g>՝ օգտագործման եղանակից կախված"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g>՝ հնարավոր է հեռախոսը շուտով կանջատվի"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g>՝ հնարավոր է պլանշետը շուտով կանջատվի"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g>՝ հնարավոր է սարքը շուտով կանջատվի"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Մինչև լրիվ լիցքավորումը մնացել է <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> մինչև լրիվ լիցքավորումը"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Անհայտ"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Լիցքավորում"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index c02bd90..3e8c676 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS Pribadi"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Pilih Mode DNS Pribadi"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Nonaktif"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Oportunistik"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Hostname penyedia DNS pribadi"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Masukkan hostname penyedia DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Tampilkan opsi untuk sertifikasi layar nirkabel"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Fitur ini bersifat eksperimental dan dapat memengaruhi kinerja."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Digantikan oleh <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Sekitar <xliff:g id="TIME">%1$s</xliff:g> lagi"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Kira-kira <xliff:g id="TIME">%1$s</xliff:g> lagi berdasarkan penggunaan Anda"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> lagi hingga terisi penuh"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> tersisa"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Tersisa kurang dari <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tersisa kurang dari <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>tersisa lebih dari <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"tersisa lebih dari <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ponsel mungkin segera dimatikan"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet mungkin segera dimatikan"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"perangkat mungkin segera dimatikan"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - kira-kira <xliff:g id="TIME">%2$s</xliff:g> lagi"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - kira-kira <xliff:g id="TIME">%2$s</xliff:g> lagi berdasarkan penggunaan Anda"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - ponsel mungkin segera dimatikan"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - tablet mungkin segera dimatikan"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - perangkat mungkin segera dimatikan"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> lagi hingga terisi penuh"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lagi terisi penuh"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Tidak diketahui"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Mengisi daya"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 36baf6c..0e90dd6 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Lokað DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Velja lokaða DNS-stillingu"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Slökkt"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Eftir hentugleika"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Hýsilheiti lokaðrar DNS-veitu"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Slá inn hýsilheiti DNS-veitu"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Sýna valkosti fyrir vottun þráðlausra skjáa"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Þessi eiginleiki er á tilraunastigi og getur haft áhrif á frammistöðu."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Hnekkt af <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Um það bil <xliff:g id="TIME">%1$s</xliff:g> eftir"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"U.þ.b. <xliff:g id="TIME">%1$s</xliff:g> eftir miðað við notkun þína"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> þar til hleðslu er lokið"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> eftir"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Minna en <xliff:g id="THRESHOLD">%1$s</xliff:g> eftir"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – Minna en <xliff:g id="THRESHOLD">%2$s</xliff:g> eftir"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>meira en <xliff:g id="TIME_REMAINING">%2$s</xliff:g> eftir"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"meira en <xliff:g id="TIME_REMAINING">%1$s</xliff:g> eftir"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"síminn gæti slökkt á sér fljótlega"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"spjaldtölvan gæti slökkt á sér fljótlega"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"tækið gæti slökkt á sér fljótlega"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – um <xliff:g id="TIME">%2$s</xliff:g> eftir"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – u.þ.b. <xliff:g id="TIME">%2$s</xliff:g> eftir miðað við notkun þína"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – síminn gæti slökkt á sér fljótlega"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – spjaldtölvan gæti slökkt á sér fljótlega"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – tækið gæti slökkt á sér fljótlega"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> þar til hleðslu er lokið"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> þar til fullri hleðslu er náð"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Óþekkt"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Í hleðslu"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index f19c14c..0ac2b8e 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS privato"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Seleziona modalità DNS privato"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Non attiva"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Opportunistica"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Nome host del provider DNS privato"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Inserisci il nome host del provider DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostra opzioni per la certificazione display wireless"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Questa funzione è sperimentale e potrebbe influire sulle prestazioni."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Valore sostituito da <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Tempo approssimativo rimanente: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Tempo rimanente in base al tuo utilizzo: <xliff:g id="TIME">%1$s</xliff:g> circa"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Tempo rimanente alla carica completa: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Tempo rimanente: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Tempo rimanente: meno di <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tempo rimanente: meno di <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tempo rimanente: più di <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"Tempo rimanente: più di <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"Il telefono potrebbe spegnersi a breve"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"Il tablet potrebbe spegnersi a breve"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"Il dispositivo potrebbe spegnersi a breve"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - ancora circa <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tempo rimanente in base al tuo utilizzo: <xliff:g id="TIME">%2$s</xliff:g> circa"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g>: il telefono potrebbe spegnersi a breve"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g>: il tablet potrebbe spegnersi a breve"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g>: il dispositivo potrebbe spegnersi a breve"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Tempo rimanente alla carica completa: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla carica completa"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Sconosciuta"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"In carica"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 81307f7..7c4eb7c 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"‏DNS פרטי"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"‏צריך לבחור במצב DNS פרטי"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"מושבת"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"אופרטוניסטי"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"‏שם מארח של ספק DNS פרטי"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"‏צריך להזין את שם המארח של ספק DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"‏הצג אפשרויות עבור אישור של תצוגת WiFi"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"תכונה זו היא ניסיונית ועשויה להשפיע על הביצועים."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"נעקף על ידי <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"עוד <xliff:g id="TIME">%1$s</xliff:g> בקירוב"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"על סמך השימוש במכשיר, הסוללה תתרוקן בעוד <xliff:g id="TIME">%1$s</xliff:g>, בקירוב"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> עד לטעינה מלאה"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"נותרו <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"נותרו פחות מ-<xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - הזמן שנותר, פחות מ-<xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>הזמן שנותר: יותר מ-<xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"הזמן שנותר: יותר מ-<xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ייתכן שהטלפון ייכבה בקרוב"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ייתכן שהטאבלט ייכבה בקרוב"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"ייתכן שהמכשיר ייכבה בקרוב"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - הזמן הנותר: בערך <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - על סמך השימוש במכשיר, הסוללה תתרוקן בעוד <xliff:g id="TIME">%2$s</xliff:g>, בקירוב"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - ייתכן שהטלפון ייכבה בקרוב"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - ייתכן שהטאבלט ייכבה בקרוב"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - ייתכן שהמכשיר ייכבה בקרוב"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g>‏ - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> עד לטעינה מלאה"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> עד לטעינה מלאה"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"לא ידוע"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"טוען"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 346a96d..c5836d6 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"プライベート DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"プライベート DNS モードを選択"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"OFF"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"日和見"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"プライベート DNS プロバイダのホスト名"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS プロバイダのホスト名を入力"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ワイヤレスディスプレイ認証のオプションを表示"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"この機能は試験運用機能であり、パフォーマンスに影響することがあります。"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g>によって上書き済み"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"あと約 <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"残り時間: 約 <xliff:g id="TIME">%1$s</xliff:g>(使用状況に基づく)"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"フル充電まであと <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g>(残り時間)"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"残り時間: <xliff:g id="THRESHOLD">%1$s</xliff:g>未満"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - 残り時間: <xliff:g id="THRESHOLD">%2$s</xliff:g>未満"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> ー 残り時間: <xliff:g id="TIME_REMAINING">%2$s</xliff:g>以上"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"残り時間: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>以上"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"スマートフォンの電源がもうすぐ切れます"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"タブレットの電源がもうすぐ切れます"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"端末の電源がもうすぐ切れます"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - 残り約 <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - 残り時間: 約 <xliff:g id="TIME">%2$s</xliff:g>(使用状況に基づく)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - スマートフォンの電源がもうすぐ切れます"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - タブレットの電源がもうすぐ切れます"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - 端末の電源がもうすぐ切れます"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"フル充電まであと <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - フル充電まで <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"不明"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"充電中"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index db03069..caf15cc 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"პირადი DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"აირჩიეთ პირადი DNS რეჟიმი"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"გამორთული"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"ოპორტუნისტული"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"პირადი DNS პროვაიდერის სერვერის სახელი"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"შეიყვანეთ DNS პროვაიდერის სერვერის სახელი"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"უსადენო ეკრანის სერტიფიცირების ვარიანტების ჩვენება"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ეს ფუნქცია საცდელია და შეიძლება გავლენა იქონიოს ფუნქციონალობაზე."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"უკუგებულია <xliff:g id="TITLE">%1$s</xliff:g>-ის მიერ"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"დარჩა დაახლოებით <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"დარჩა დაახლოებით <xliff:g id="TIME">%1$s</xliff:g>, ბატარეის მოხმარების გათვალისწინებით"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"სრულ დატენვამდე დარჩენილია <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"დარჩენილია <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"დარჩენილია <xliff:g id="THRESHOLD">%1$s</xliff:g>-ზე ნაკლები"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> — დარჩენილია <xliff:g id="THRESHOLD">%2$s</xliff:g>-ზე ნაკლები"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>დარჩენილია <xliff:g id="TIME_REMAINING">%2$s</xliff:g>-ზე მეტი"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"დარჩენილია <xliff:g id="TIME_REMAINING">%1$s</xliff:g>-ზე მეტი"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ტელეფონი შეიძლება მალე გაითიშოს"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ტაბლეტი შეიძლება მალე გაითიშოს"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"მოწყობილობა შეიძლება მალე გაითიშოს"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> — დარჩა დაახლოებით <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> — დარჩა დაახლოებით <xliff:g id="TIME">%2$s</xliff:g>, ბატარეის მოხმარების გათვალისწინებით"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> — ტელეფონი შეიძლება მალე გაითიშოს"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> — ტაბლეტი შეიძლება მალე გაითიშოს"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> — მოწყობილობა შეიძლება მალე გაითიშოს"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"სრულ დატენვამდე დარჩენილია <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> — სრულ დატენვამდე დარჩა <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"უცნობი"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"იტენება"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index acd7d87..08733ae 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Жеке DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Жеке DNS режимін таңдаңыз"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Өшіру"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Кездейсоқ"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Жеке DNS провайдерінің хост атауы"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS провайдерінің хост атауын енгізіңіз"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Сымсыз дисплей растау опцияларын көрсету"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Бұл мүмкіндік эксперименттік болып табылады және өнімділікке әсер етуі мүмкін."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> үстінен басқан"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Қалған <xliff:g id="TIME">%1$s</xliff:g> туралы"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Пайдалану негізінде шамамен <xliff:g id="TIME">%1$s</xliff:g> қалды"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Толық зарядқа <xliff:g id="TIME">%1$s</xliff:g> қалды"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> қалды"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> шамасынан аз қалды"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="THRESHOLD">%2$s</xliff:g> шамасынан аз қалды"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g><xliff:g id="TIME_REMAINING">%2$s</xliff:g> үстінде қалды"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> үстінде қалды"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"телефон көп ұзамай өшуі мүмкін"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"планшет көп ұзамай өшуі мүмкін"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"құрылғы көп ұзамай өшуі мүмкін"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – шамамен <xliff:g id="TIME">%2$s</xliff:g> қалды"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - пайдалану негізінде шамамен <xliff:g id="TIME">%2$s</xliff:g> қалды"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – телефон көп ұзамай өшуі мүмкін"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – планшет көп ұзамай өшуі мүмкін"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – құрылғы көп ұзамай өшуі мүмкін"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Толық зарядқа <xliff:g id="TIME">%1$s</xliff:g> қалды"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – толық зарядталғанға дейін <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Белгісіз"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Зарядталуда"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 3da3758..57022a8 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS ឯកជន"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"ជ្រើសរើសមុខងារ DNS ឯកជន"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"បិទ"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Opportunistic"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"ឈ្មោះម៉ាស៊ីនក្រុមហ៊ុនផ្ដល់សេវា DNS ឯកជន"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"បញ្ចូលឈ្មោះម៉ាស៊ីនរបស់ក្រុមហ៊ុនផ្ដល់សេវា DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"បង្ហាញ​ជម្រើស​សម្រាប់​វិញ្ញាបនបត្រ​បង្ហាញ​ឥត​ខ្សែ"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"មុខងារនេះ​គឺ​ជា​ការ​ពិសោធន៍ ហើយ​អាច​ប៉ះពាល់​ដំណើរការ​។"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"បដិសេធ​ដោយ <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"សល់​ប្រហែល <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"សល់ប្រហែល <xliff:g id="TIME">%1$s</xliff:g> ទៀតផ្អែកលើការប្រើប្រាស់របស់អ្នក"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"សល់ <xliff:g id="TIME">%1$s</xliff:g> ទើប​សាកថ្ម​ពេញ"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"នៅសល់ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"នៅ​សល់​តិច​ជាង <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g>៖ នៅ​សល់​តិច​ជាង <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>៖ នៅ​សល់​ច្រើន​ជាង <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"នៅ​សល់​ច្រើន​ជាង <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ទូរសព្ទ​អាច​នឹង​បិទ​ក្នុង​ពេល​បន្តិច​ទៀត"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ថេប្លេត​អាច​នឹង​បិទ​ក្នុង​ពេល​បន្តិច​ទៀត"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"ឧបករណ៍​អាច​នឹង​បិទ​ក្នុង​ពេល​បន្តិច​ទៀត"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - សល់ប្រហែល <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - សល់ប្រហែល <xliff:g id="TIME">%2$s</xliff:g> ទៀតផ្អែកលើការប្រើប្រាស់របស់អ្នក"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g>៖ ទូរសព្ទ​អាច​នឹង​បិទ​ក្នុង​ពេល​បន្តិច​ទៀត"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g>៖ ថេប្លេត​អាច​នឹង​បិទ​ក្នុង​ពេល​បន្តិច​ទៀត"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g>៖ ឧបករណ៍​អាច​នឹង​បិទ​ក្នុង​ពេល​បន្តិច​ទៀត"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"សល់ <xliff:g id="TIME">%1$s</xliff:g> ទើប​សាកថ្ម​ពេញ"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> រហូតដល់សាកពេញ"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"មិន​ស្គាល់"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"កំពុងបញ្ចូល​ថ្ម"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 9f55983..8a5b251 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"ಖಾಸಗಿ DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"ಖಾಸಗಿ DNS ಮೋಡ್ ಆಯ್ಕೆಮಾಡಿ"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"ಆಫ್"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"ಅವಕಾಶವಾದಿ"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"ಖಾಸಗಿ DNS ಪೂರೈಕೆದಾರರ ಹೋಸ್ಟ್‌ಹೆಸರು"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ಪೂರೈಕೆದಾರರ ಹೋಸ್ಟ್‌ಹೆಸರನ್ನು ನಮೂದಿಸಿ"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ವೈರ್‌ಲೆಸ್‌‌‌ ಪ್ರದರ್ಶನ ಪ್ರಮಾಣೀಕರಣಕ್ಕಾಗಿ ಆಯ್ಕೆಗಳನ್ನು ತೋರಿಸು"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ಇದು ಪ್ರಾಯೋಗಿಕ ವೈಶಿಷ್ಟ್ಯವಾಗಿದೆ. ಕಾರ್ಯಕ್ಷಮತೆ ಮೇಲೆ ಪರಿಣಾಮ ಬೀರಬಹುದು."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ಮೂಲಕ ಅತಿಕ್ರಮಿಸುತ್ತದೆ"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"ಸುಮಾರು <xliff:g id="TIME">%1$s</xliff:g> ಬಾಕಿಯಿದೆ"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"ನಿಮ್ಮ ಬಳಕೆಯ ಆಧಾರದ ಮೇಲೆ ಸುಮಾರು <xliff:g id="TIME">%1$s</xliff:g> ಉಳಿದಿದೆ"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"ಸಂಪೂರ್ಣ ಚಾರ್ಜ್ ಆಗಲು <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> ಉಳಿದಿದೆ"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> ನಿಮಿಷಕ್ಕಿಂತ ಕಡಿಮೆ ಸಮಯ ಉಳಿದಿದೆ"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - ರಷ್ಟು <xliff:g id="THRESHOLD">%2$s</xliff:g> ಕ್ಕಿಂತ ಕಡಿಮೆ ಸಮಯ ಬಾಕಿ ಉಳಿದಿದೆ"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> ರಷ್ಟು <xliff:g id="TIME_REMAINING">%2$s</xliff:g> ಕ್ಕಿಂತ ಹೆಚ್ಚು ಸಮಯ ಬಾಕಿ ಉಳಿದಿದೆ"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ಕ್ಕಿಂತ ಹೆಚ್ಚು ಸಮಯ ಉಳಿದಿದೆ"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ಫೋನ್ ಶೀಘ್ರದಲ್ಲೇ ಶಟ್ ಡೌನ್ ಆಗಬಹುದು"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ಟ್ಯಾಬ್ಲೆಟ್‌‌ ಶೀಘ್ರದಲ್ಲೇ ಶಟ್ ಡೌನ್ ಆಗಬಹುದು"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"ಸಾಧನವು ಶೀಘ್ರದಲ್ಲೇ ಶಟ್ ಡೌನ್ ಆಗಬಹುದು"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಸುಮಾರು <xliff:g id="TIME">%2$s</xliff:g> ಬಾಕಿಯಿದೆ"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - ನಿಮ್ಮ ಬಳಕೆಯ ಆಧಾರದ ಮೇಲೆ <xliff:g id="TIME">%2$s</xliff:g> ಉಳಿದಿದೆ"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಫೋನ್ ಶೀಘ್ರದಲ್ಲೇ ಶಟ್ ಡೌನ್ ಆಗಬಹುದು"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಟ್ಯಾಬ್ಲೆಟ್‌‌ ಶೀಘ್ರದಲ್ಲೇ ಶಟ್ ಡೌನ್ ಆಗಬಹುದು"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಸಾಧನವು ಶೀಘ್ರದಲ್ಲೇ ಶಟ್ ಡೌನ್ ಆಗಬಹುದು"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"ಸಂಪೂರ್ಣ ಚಾರ್ಜ್ ಆಗಲು <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಸಂಪೂರ್ಣ ಚಾರ್ಜ್ ಆಗಲು <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"ಅಪರಿಚಿತ"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 35a2867..af1859a 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"비공개 DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"비공개 DNS 모드 선택"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"사용 안함"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"기회주의적"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"비공개 DNS 제공업체 호스트 이름"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS 제공업체의 호스트 이름 입력"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"무선 디스플레이 인증서 옵션 표시"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"실험실 기능이며 성능에 영향을 줄 수 있습니다."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> 우선 적용됨"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"약 <xliff:g id="TIME">%1$s</xliff:g> 남음"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"내 사용량을 기준으로 약 <xliff:g id="TIME">%1$s</xliff:g> 남음"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"충전 완료까지 <xliff:g id="TIME">%1$s</xliff:g> 남음"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> 남음"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> 미만 남음"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g> 미만 남음"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g><xliff:g id="TIME_REMAINING">%2$s</xliff:g> 이상 남음"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> 이상 남음"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"휴대전화가 곧 종료될 수 있음"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"태블릿이 곧 종료될 수 있음"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"기기가 곧 종료될 수 있음"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - 약 <xliff:g id="TIME">%2$s</xliff:g> 남음"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - 내 사용량을 기준으로 약 <xliff:g id="TIME">%2$s</xliff:g> 남음"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - 휴대전화가 곧 종료될 수 있음"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - 태블릿이 곧 종료될 수 있음"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - 기기가 곧 종료될 수 있음"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"충전 완료까지 <xliff:g id="TIME">%1$s</xliff:g> 남음"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - 충전 완료까지 <xliff:g id="TIME">%2$s</xliff:g> 남음"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"알 수 없음"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"충전 중"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index c1f73cc..baf2753 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Купуя DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Купуя DNS режимин тандаңыз"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Өчүк"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Ийкемдүү"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Купуя DNS түйүндүн аталышы"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS түйүндүн аталышын киргизиңиз"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Зымсыз дисплейди сертификатто мүмкүнчүлүктөрүн көргөзүү"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Бул сынамык мүмкүнчүлүк болгондуктан, түзмөктүн иштешине таасир этиши мүмкүн."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> менен алмаштырылган"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Батарея түгөнгөнгө чейин калган убакыт: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Колдонушуңузга караганда болжол менен <xliff:g id="TIME">%1$s</xliff:g> калды"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Батарея толгонго чейин калган убакыт: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> калды"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> жетпеген убакыт калды"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="THRESHOLD">%2$s</xliff:g> жетпеген убакыт калды"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME_REMAINING">%2$s</xliff:g> көп убакыт калды"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> көп убакыт калды"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"телефон бир аздан кийин өчүп калышы мүмкүн"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"планшет бир аздан кийин өчүп калышы мүмкүн"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"түзмөк бир аздан кийин өчүп калышы мүмкүн"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – болжол менен <xliff:g id="TIME">%2$s</xliff:g> калды"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - колдонушуңузга караганда болжол менен <xliff:g id="TIME">%2$s</xliff:g> калды"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – телефон бир аздан кийин өчүп калышы мүмкүн"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – планшет бир аздан кийин өчүп калышы мүмкүн"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – түзмөк бир аздан кийин өчүп калышы мүмкүн"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Батарея толгонго чейин калган убакыт: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> кийин толук кубатталат"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Белгисиз"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Кубатталууда"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index a5c8d56..5f673f2b 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS ສ່ວນຕົວ"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"ເລືອກໂໝດ DNS ສ່ວນຕົວ"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"ປິດ"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"ກ່ຽວກັບໂອກາດ"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"ຊື່ໂຮສຜູ້ໃຫ້ບໍລິການ DNS ສ່ວນຕົວ"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"ລະບຸຊື່ໂຮສຂອງຜູ້ໃຫ້ບໍລິການ DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ສະແດງໂຕເລືອກສຳລັບການສະແດງການຮັບຮອງລະບົບໄຮ້ສາຍ"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"​ຄຸນ​ສົມ​ບັດ​ນີ້​ກຳ​ລັງ​ຢູ່​ໃນ​ການ​ທົດ​ລອງ​ແລະ​ອາດ​ມີ​ຜົນ​ຕໍ່​ປະ​ສິດ​ທິ​ພາບ."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"ຖືກແທນໂດຍ <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"ອີກປະມານ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"ເຫຼືອອີກປະມານ <xliff:g id="TIME">%1$s</xliff:g> ໂດຍອ້າງອີງຈາກການນຳໃຊ້ຂອງທ່ານ"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> ຈົນກວ່າຈະສາກເຕັມ"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"ຍັງເຫຼືອ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"ຍັງເຫຼືອໜ້ອຍກວ່າ <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - ຍັງເຫຼືອໜ້ອຍກວ່າ <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>ຍັງເຫຼືອຫຼາຍກວ່າ <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"ຍັງເຫຼືອຫຼາຍກວ່າ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ໂທລະສັບອາດຈະປິດໃນໄວໆນີ້"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ແທັຍເລັດອາດຈະປິດໃນໄວໆນີ້"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"ອຸປະກອນອາດຈະປິດໃນໄວໆນີ້"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - ຍັງເຫຼືອປະມານ <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - ເຫຼືອອີກປະມານ <xliff:g id="TIME">%2$s</xliff:g> ໂດຍອ້າງອີງຈາກການນຳໃຊ້ຂອງທ່ານ"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - ໂທລະສັບອາດຈະປິດໃນໄວໆນີ້"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - ແທັບເລັດອາດຈະປິດໃນໄວໆນີ້"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - ອຸປະກອນອາດຈະປິດໃນໄວໆນີ້"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> ຈົນກວ່າຈະສາກເຕັມ"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈົນກວ່າຈະສາກເຕັມ"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"ບໍ່ຮູ້ຈັກ"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"ກຳລັງສາກໄຟ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 8eced2d..eb48b7f 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Privatus DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Pasirinkite privataus DNS režimą"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Išjungta"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Oportunistinis"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Privataus DNS teikėjo prieglobos serverio pavadinimas"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Įveskite DNS teikėjo prieglobos serverio pavadinimą"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Rodyti belaidžio rodymo sertifikavimo parinktis"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ši funkcija yra eksperimentinė ir ji gali turėti įtakos našumui."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Nepaisyta naudojant nuostatą „<xliff:g id="TITLE">%1$s</xliff:g>“"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Liko maždaug <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Liko maždaug <xliff:g id="TIME">%1$s</xliff:g>, atsižvelgiant į naudojimą"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Iki visiškos įkrovos liko <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Liko <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Liko mažiau nei <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – liko mažiau nei <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – liko daugiau nei <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"Liko daugiau nei <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefonas netrukus gali būti išjungtas"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"planšetinis komp. netrukus gali būti išjungtas"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"įrenginys netrukus gali būti išjungtas"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – liko maždaug <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – liko maždaug <xliff:g id="TIME">%2$s</xliff:g>, atsižvelgiant į naudojimą"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – telefonas netrukus gali būti išjungtas"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – planšetinis kompiuteris netrukus gali būti išjungtas"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – įrenginys netrukus gali būti išjungtas"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Iki visiškos įkrovos liko <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> iki visiško įkrovimo"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Nežinomas"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Kraunasi..."</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 24cc69e..96a9d1e 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Privāts DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Atlasiet privāta DNS režīmu"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Izslēgts"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Oportūnistisks"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Privātā DNS pakalpojumu sniedzēja saimniekdatora nosaukums"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Ievadiet DNS pakalpojumu sniedzēja saimniekdatora nosaukumu"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Rādīt bezvadu attēlošanas sertifikācijas iespējas"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Šī funkcija ir eksperimentāla un var ietekmēt veiktspēju."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Jaunā preference: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Atlikušais laiks: aptuveni <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Atlikušais laiks: aptuveni <xliff:g id="TIME">%1$s</xliff:g> (ņemot vērā lietojumu)"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Atlikušais laiks līdz pilnai uzlādei: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Atlicis: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Atlikušais laiks — mazāk nekā <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> — atlikušais laiks ir mazāk nekā <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> — atlikušais laiks ir vairāk nekā <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"Atlikušais laiks — vairāk nekā <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"Tālrunis, iespējams, drīz izslēgsies."</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"Planšetdators, iespējams, drīz izslēgsies."</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"Ierīce, iespējams, drīz izslēgsies."</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - vēl apmēram <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> — atlikušais laiks: aptuveni <xliff:g id="TIME">%2$s</xliff:g> (ņemot vērā lietojumu)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> — tālrunis, iespējams, drīz izslēgsies."</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> — planšetdators, iespējams, drīz izslēgsies."</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> — ierīce, iespējams, drīz izslēgsies."</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Atlikušais laiks līdz pilnai uzlādei: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>, kamēr pilnībā uzlādēts"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Nezināms"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Uzlāde"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 4798a6f..534e994 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Приватен DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Изберете режим на приватен DNS"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Исклучено"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Опортунистички"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Име на хост на оператор на приватен DNS"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Внесете име на хост на операторот на DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Покажи ги опциите за безжичен приказ на сертификат"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Функцијата е експериментална и може да влијае на изведбата."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Прескокнато според <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Преостануваат околу <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Уште околу <xliff:g id="TIME">%1$s</xliff:g> според користењето"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Преостануваат <xliff:g id="TIME">%1$s</xliff:g> дури се наполни целосно"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"уште <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Уште помалку од <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Уште помалку од <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>- Уште повеќе од <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"Уште повеќе од <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"телефонот може да се исклучи наскоро"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"таблетот може да се исклучи наскоро"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"уредот може да се исклучи наскоро"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - уште околу <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - уште околу <xliff:g id="TIME">%2$s</xliff:g> според користењето"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - телефонот може да се исклучи наскоро"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - таблетот може да се исклучи наскоро"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - уредот може да се исклучи наскоро"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Преостануваат <xliff:g id="TIME">%1$s</xliff:g> дури се наполни целосно"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> дури се наполни целосно"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Непознато"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Се полни"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 04b08f4..20a1e29 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"സ്വകാര്യ DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"സ്വകാര്യ DNS മോഡ് തിരഞ്ഞെടുക്കുക"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"ഓഫ്"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"അവസരവാദപരം"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"സ്വകാര്യ DNS ദാതാവിന്‍റെ ഹോസ്റ്റുനാമം"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ദാതാവിന്‍റെ ഹോസ്റ്റുനാമം നൽകുക"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"വയർലെസ് ഡിസ്‌പ്ലേ സർട്ടിഫിക്കേഷനായി ഓപ്‌ഷനുകൾ ദൃശ്യമാക്കുക"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ഈ ഫീച്ചർ പരീക്ഷണാത്മകമായതിനാൽ പ്രകടനത്തെ ബാധിച്ചേക്കാം."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ഉപയോഗിച്ച് അസാധുവാക്കി"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"ഏകദേശം <xliff:g id="TIME">%1$s</xliff:g> ശേഷിക്കുന്നു"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"നിങ്ങളുടെ ഉപയോഗത്തെ അടിസ്ഥാനമാക്കി ഏതാണ്ട് <xliff:g id="TIME">%1$s</xliff:g> ശേഷിക്കുന്നു"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"മുഴുവൻ ചാർജാകാൻ <xliff:g id="TIME">%1$s</xliff:g> ശേഷിക്കുന്നു"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> ശേഷിക്കുന്നു"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g>-ൽ കുറവ് സമയം ശേഷിക്കുന്നു"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g>-ൽ കുറവ് സമയം ശേഷിക്കുന്നു"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g><xliff:g id="TIME_REMAINING">%2$s</xliff:g>-ൽ കൂടുതൽ സമയം ശേഷിക്കുന്നു"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>-ൽ കൂടുതൽ സമയം ശേഷിക്കുന്നു"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ഫോൺ ഉടൻ ഷട്ട് ഡൗൺ ആയേക്കാം"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ടാബ്‌ലെറ്റ് ഉടൻ ഷട്ട് ഡൗൺ ആയേക്കാം"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"ഉപകരണം ഉടൻ ഷട്ട്ഡൗൺ ആയേക്കാം"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - ഏതാണ്ട് <xliff:g id="TIME">%2$s</xliff:g> ശേഷിക്കുന്നു"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - നിങ്ങളുടെ ഉപയോഗത്തെ അടിസ്ഥാനമാക്കി ഏതാണ്ട് <xliff:g id="TIME">%2$s</xliff:g> ശേഷിക്കുന്നു"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - ഫോൺ ഉടൻ ഷട്ട് ഡൗൺ ആയേക്കാം"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - ടാബ്‌ലെറ്റ് ഉടൻ ഷട്ട് ഡൗൺ ആയേക്കാം"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - ഉപകരണം ഉടൻ ഷട്ട്ഡൗൺ ആയേക്കാം"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"മുഴുവൻ ചാർജാകാൻ <xliff:g id="TIME">%1$s</xliff:g> ശേഷിക്കുന്നു"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - ഫുൾ ചാർജാകാൻ <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"അജ്ഞാതം"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"ചാർജ്ജുചെയ്യുന്നു"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 596d103..04ca84ac 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Хувийн DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Хувийн DNS Горимыг сонгох"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Унтраалттай"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Оппортунист үзэлтэн"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Хувийн DNS-н үйлчилгээ үзүүлэгчийн хостын нэр"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS-н үйлчилгээ үзүүлэгчийн хостын нэрийг оруулах"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Утасгүй дэлгэцийн сертификатын сонголтыг харуулах"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Энэ функц туршилтынх бөгөөд ажиллагаанд нөлөөлж болзошгүй."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Давхарласан <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Ойролцоогоор <xliff:g id="TIME">%1$s</xliff:g> үлдсэн"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Таны хэрэглээнд тулгуурлан <xliff:g id="TIME">%1$s</xliff:g> орчмын хугацаа үлдсэн байна"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Бүрэн цэнэглэх хүртэл <xliff:g id="TIME">%1$s</xliff:g> үлдсэн"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> үлдсэн"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g>-с бага хугацаа үлдсэн"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g>-с бага хугацаа үлдсэн"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g><xliff:g id="TIME_REMAINING">%2$s</xliff:g>-с их хугацаа үлдсэн"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>-с их хугацаа үлдсэн"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"утас удахгүй унтарч болзошгүй"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"таблет удахгүй унтарч болзошгүй"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"төхөөрөмж удахгүй унтарч болзошгүй"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g>-с <xliff:g id="TIME">%2$s</xliff:g> үлдсэн"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - таны хэрэглээнд тулгуурлан <xliff:g id="TIME">%2$s</xliff:g> орчмын хугацаа үлдсэн байна"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - утас удахгүй унтарч болзошгүй"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - таблет удахгүй унтарч болзошгүй"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - төхөөрөмж удахгүй унтарч болзошгүй"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Бүрэн цэнэглэх хүртэл <xliff:g id="TIME">%1$s</xliff:g> үлдсэн"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"бүрэн цэнэглэх хүртэл <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Тодорхойгүй"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Цэнэглэж байна"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 26f4344..de93282 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"खाजगी DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"खाजगी DNS मोड निवडा"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"बंद"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"संधिसाधू"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"खाजगी DNS पुरवठादार होस्ट नाव"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS पुरवठादाराचे होस्टनाव टाका"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"वायरलेस डिस्प्ले प्रमाणिकरणाचे पर्याय दाखवा"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"हे वैशिष्‍ट्य प्रायोगिक आहे आणि कदाचित कार्यप्रदर्शन प्रभावित करू शकते."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> द्वारे अधिलिखित"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"सुमारे <xliff:g id="TIME">%1$s</xliff:g> शिल्‍लक"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"तुमच्या वापरानुसार अंदाजे <xliff:g id="TIME">%1$s</xliff:g> पुरेल इतकी बॅटरी शिल्लक आहे"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"पूर्णपणे चार्ज होण्यास <xliff:g id="TIME">%1$s</xliff:g> शिल्‍लक"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> शिल्लक"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> पेक्षा कमी शिल्लक आहे"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g> पेक्षा कमी शिल्लक आहे"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g><xliff:g id="TIME_REMAINING">%2$s</xliff:g> पेक्षा जास्त शिल्लक आहे"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> पेक्षा जास्त शिल्लक आहे"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"फोन लवकरच बंद होऊ शकतो"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"टॅबलेट लवकरच बंद होऊ शकतो"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"डिव्हाइस लवकरच बंद होऊ शकते"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - सुमारे <xliff:g id="TIME">%2$s</xliff:g> शिल्लक"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - तुमच्या वापरानुसार अंदाजे <xliff:g id="TIME">%2$s</xliff:g> पुरेल इतकी बॅटरी शिल्लक आहे"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - फोन लवकरच बंद होऊ शकतो"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - टॅबलेट लवकरच बंद होऊ शकतो"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - डिव्हाइस लवकरच बंद होऊ शकते"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"पूर्णपणे चार्ज होण्यास <xliff:g id="TIME">%1$s</xliff:g> शिल्‍लक"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - पूर्णपणे चार्ज होण्यात <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"अज्ञात"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"चार्ज होत आहे"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 8e24cee..99f6c0a 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS Peribadi"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Pilih Mod DNS Peribadi"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Mati"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Oportunistik"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Nama hos pembekal DNS peribadi"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Masukkan nama hos pembekal DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Tunjukkan pilihan untuk pensijilan paparan wayarles"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ciri ini adalah percubaan dan boleh menjejaskan prestasi."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Diatasi oleh <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Kira-kira <xliff:g id="TIME">%1$s</xliff:g> lagi"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Tinggal kira-kira <xliff:g id="TIME">%1$s</xliff:g> berdasarkan penggunaan anda"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> lagi sehingga dicas penuh"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> lagi"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Tinggal kurang daripada <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tinggal kurang daripada <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>tinggal lebih daripada <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"tinggal lebih daripada <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefon mungkin ditutup tidak lama lagi"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet mungkin ditutup tidak lama lagi"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"peranti mungkin ditutup tidak lama lagi"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - kira-kira <xliff:g id="TIME">%2$s</xliff:g> lagi"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - tinggal kira-kira <xliff:g id="TIME">%2$s</xliff:g> berdasarkan penggunaan anda"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - telefon mungkin ditutup tidak lama lagi"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - tablet mungkin ditutup tidak lama lagi"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - peranti mungkin ditutup tidak lama lagi"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> lagi sehingga dicas penuh"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sehingga dicas penuh"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Tidak diketahui"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Mengecas"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index c1ca0ab..aedb291 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -45,7 +45,7 @@
     <string name="available_via_carrier" msgid="1469036129740799053">"%1$s မှတစ်ဆင့် ရနိုင်သည်"</string>
     <string name="speed_label_very_slow" msgid="1867055264243608530">"အလွန်နှေး"</string>
     <string name="speed_label_slow" msgid="813109590815810235">"နှေး"</string>
-    <string name="speed_label_okay" msgid="2331665440671174858">"အိုကေ"</string>
+    <string name="speed_label_okay" msgid="2331665440671174858">"OK"</string>
     <string name="speed_label_medium" msgid="3175763313268941953">"အတော်အသင့်"</string>
     <string name="speed_label_fast" msgid="7715732164050975057">"မြန်"</string>
     <string name="speed_label_very_fast" msgid="2265363430784523409">"အလွန်မြန်"</string>
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"သီးသန့် DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"သီးသန့် DNS မုဒ်ကို ရွေးပါ"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"ပိတ်ရန်"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"အခွင့်အရေးသမား"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"သီးသန့် DNS ပံ့ပိုးသူ၏ အင်တာနက်လက်ခံဝန်ဆောင်ပေးသူအမည်"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ဝန်ဆောင်မှုပေးသူ၏ အင်တာနက်လက်ခံဝန်ဆောင်ပေးသူအမည်ကို ထည့်ပါ"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ကြိုးမဲ့ အခင်းအကျင်း အသိအမှတ်ပြုလက်မှတ်အတွက် ရွေးချယ်စရာများပြရန်"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ဤဝန်ဆောင်မှုမှာ စမ်းသပ်အဆင့်သာဖြစ်၍ လုပ်ဆောင်မှုအားနည်းနိုင်သည်။"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> မှ ကျော်၍ လုပ်ထားသည်။"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"<xliff:g id="TIME">%1$s</xliff:g> ခန့်လိုပါသည်"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"သင့်အသုံးပြုမှုအရ <xliff:g id="TIME">%1$s</xliff:g> ခန့် ကျန်ပါသည်"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"အားပြည့်ရန် <xliff:g id="TIME">%1$s</xliff:g> လိုပါသည်"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> ကျန်သည်"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> ခန့်သာ ကျန်တော့သည်"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g> ခန့်သာ ကျန်တော့သည်"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g><xliff:g id="TIME_REMAINING">%2$s</xliff:g> ကျော် ကျန်သေးသည်"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ကျော် ကျန်သေးသည်"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"မကြာမီ ဖုန်းပိတ်သွားနိုင်သည်"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"မကြာမီ တက်ဘလက်ပိတ်သွားနိုင်သည်"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"မကြာမီ စက်ပိတ်သွားနိုင်သည်"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> − <xliff:g id="TIME">%2$s</xliff:g> ခန့်ကျန်သည်"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - သင့်အသုံးပြုမှုအရ <xliff:g id="TIME">%2$s</xliff:g> ခန့် ကျန်ပါသည်"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - မကြာမီ ဖုန်းပိတ်သွားနိင်သည်"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - မကြာမီ တက်ဘလက်ပိတ်သွားနိင်သည်"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - မကြာမီ စက်ပိတ်သွားနိင်သည်"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"အားပြည့်ရန် <xliff:g id="TIME">%1$s</xliff:g> လိုပါသည်"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> − အားပြည့်ရန် <xliff:g id="TIME">%2$s</xliff:g> ကျန်သည်"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"အကြောင်းအရာ မသိရှိ"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"အားသွင်းနေပါသည်"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 0b54624..fadf154 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Privat DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Velg Privat DNS-modus"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Av"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Opportunistisk"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Vertsnavn for privat DNS-leverandør"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Skriv inn vertsnavnet til DNS-leverandøren"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Vis alternativer for sertifisering av trådløs skjerm"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Dette er en eksperimentell funksjon som kan gjøre at telefonen ikke fungerer optimalt."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overstyres av <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Omtrent <xliff:g id="TIME">%1$s</xliff:g> gjenstår"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Omtrent <xliff:g id="TIME">%1$s</xliff:g> igjen basert på bruken din"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> til det er fulladet"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> gjenstår"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Mindre enn <xliff:g id="THRESHOLD">%1$s</xliff:g> gjenstår"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – mindre enn <xliff:g id="THRESHOLD">%2$s</xliff:g> gjenstår"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> mindre enn <xliff:g id="TIME_REMAINING">%2$s</xliff:g> gjenstår"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"mer enn <xliff:g id="TIME_REMAINING">%1$s</xliff:g> gjenstår"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefonen slås kanskje av snart"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"nettbrettet slås kanskje av snart"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"enheten slås kanskje av snart"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – omtrent <xliff:g id="TIME">%2$s</xliff:g> gjenstår"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – omtrent <xliff:g id="TIME">%2$s</xliff:g> igjen basert på bruken din"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – telefonen slås kanskje av snart"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – nettbrettet slås kanskje av snart"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – enheten slås kanskje av snart"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> til det er fulladet"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> til det er fulladet"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Ukjent"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Lader"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 7b78009..e778c8e 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"निजी DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"निजी DNS मोड चयन गर्नुहोस्"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"निष्क्रिय छ"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"अवसरवादी"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"निजी DNS प्रदायकको होस्टनाम"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS प्रदायकको होस्टनाम प्रविष्ट गर्नुहोस्"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ताररहित प्रदर्शन प्रमाणीकरणका लागि विकल्पहरू देखाउनुहोस्"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"यो सुविधा प्रयोगात्मक छ र प्रदर्शनमा असर गर्न सक्छ।"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> द्वारा अधिरोहित"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"लगभग <xliff:g id="TIME">%1$s</xliff:g> बाँकी"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"तपाईंको प्रयोगका आधारमा लगभग <xliff:g id="TIME">%1$s</xliff:g> बाँकी"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"पूर्णरूपमा चार्ज हुन <xliff:g id="TIME">%1$s</xliff:g> बाँकी"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"बाँकी समय <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> भन्दा कम समय बाँकी छ"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g> भन्दा कम समय बाँकी छ"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> <xliff:g id="TIME_REMAINING">%2$s</xliff:g> भन्दा बढी समय बाँकी छ"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> भन्दा बढी समय बाँकी छ"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"फोन चाँडै बन्द हुन सक्छ"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ट्याब्लेट चाँडै बन्द हुन सक्छ"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"यन्त्र चाँडै बन्द हुन सक्छ"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - करिब <xliff:g id="TIME">%2$s</xliff:g> बाँकी"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - तपाईंको प्रयोगका आधारमा लगभग <xliff:g id="TIME">%2$s</xliff:g> बाँकी"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - फोन चाँडै बन्द हुन सक्छ"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - ट्याब्लेट चाँडै बन्द हुन सक्छ"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - यन्त्र चाँडै बन्द हुन सक्छ"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"पूर्णरूपमा चार्ज हुन <xliff:g id="TIME">%1$s</xliff:g> बाँकी"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - पूर्णरूपमा चार्ज हुन <xliff:g id="TIME">%2$s</xliff:g> बाँकी"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"अज्ञात"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"चार्ज हुँदै"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index c6577e6..dc56ac4 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Privé-DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Selecteer de modus Privé-DNS"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Uit"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Opportunistisch"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Hostnaam van privé-DNS-provider"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Geef hostnaam van DNS-provider op"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Opties weergeven voor certificering van draadloze weergave"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Deze functie is experimenteel en kan invloed hebben op de prestaties."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overschreven door <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Nog ongeveer <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Nog ongeveer <xliff:g id="TIME">%1$s</xliff:g> over op basis van je gebruik"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Nog <xliff:g id="TIME">%1$s</xliff:g> tot volledig opgeladen"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> resterend"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Minder dan <xliff:g id="THRESHOLD">%1$s</xliff:g> resterend"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Minder dan <xliff:g id="THRESHOLD">%2$s</xliff:g> resterend"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> - meer dan <xliff:g id="TIME_REMAINING">%2$s</xliff:g> resterend"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"meer dan <xliff:g id="TIME_REMAINING">%1$s</xliff:g> resterend"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefoon wordt binnenkort mogelijk uitgeschakeld"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet wordt binnenkort mogelijk uitgeschakeld"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"apparaat wordt binnenkort mogelijk uitgeschakeld"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - ongeveer <xliff:g id="TIME">%2$s</xliff:g> resterend"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g>: nog ongeveer <xliff:g id="TIME">%2$s</xliff:g> over op basis van je gebruik"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - telefoon wordt binnenkort mogelijk uitgeschakeld"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - tablet wordt binnenkort mogelijk uitgeschakeld"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - apparaat wordt binnenkort mogelijk uitgeschakeld"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Nog <xliff:g id="TIME">%1$s</xliff:g> tot volledig opgeladen"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tot volledig opgeladen"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Onbekend"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Opladen"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 0c2cbda..ab7e9fa 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -233,7 +233,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"ବ୍ୟକ୍ତିଗତ DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"ବ୍ୟକ୍ତିଗତ DNS ମୋଡ୍‌ ବାଛନ୍ତୁ"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"ଅଫ୍"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"ସୁଯୋଗବାଦୀ"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"ବ୍ୟକ୍ତିଗତ DNS ପ୍ରଦାତା ହୋଷ୍ଟନାମ"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ପ୍ରଦାନକାରୀଙ୍କ ହୋଷ୍ଟନାମ ପ୍ରବେଶ କରନ୍ତୁ"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ୱେୟାରଲେସ୍‌ ପ୍ରଦର୍ଶନ ସାର୍ଟିଫିକେସନ୍‌ ପାଇଁ ବିକଳ୍ପଗୁଡିକ ଦେଖାନ୍ତୁ"</string>
@@ -372,32 +373,42 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ଏହି ପରୀକ୍ଷାମୂଳକ ବୈଶିଷ୍ଟ୍ୟ ପର୍ଫର୍ମେନ୍ସକୁ ପ୍ରଭାବିତ କରିପାରେ।"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ଦ୍ୱାରା ଓଭର୍‌ରାଇଡ୍‌ କରାଯାଇଛି"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"ପ୍ରାୟ <xliff:g id="TIME">%1$s</xliff:g> ଅବଶିଷ୍ଟ ରହିଛି"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"ଆପଣଙ୍କ ବ୍ୟବହାରକୁ ଆଧାର କରି ପ୍ରାୟ <xliff:g id="TIME">%1$s</xliff:g> ଅବଶିଷ୍ଟ"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"ସମ୍ପୂର୍ଣ୍ଣ ଚାର୍ଜ ହେବାପାଇଁ <xliff:g id="TIME">%1$s</xliff:g> ଅବଶିଷ୍ଟ ଅଛି"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> ଅବଶିଷ୍ଟ"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <!-- no translation found for power_remaining_less_than_duration_only (5996752448813295329) -->
     <skip />
-    <!-- no translation found for power_remaining_less_than_duration (7967078125657859046) -->
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
     <skip />
-    <!-- no translation found for power_remaining_more_than_subtext (6846716609975752316) -->
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
     <skip />
-    <!-- no translation found for power_remaining_only_more_than_subtext (8884488700395194194) -->
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
     <skip />
-    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (8168317165722752881) -->
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
     <skip />
-    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (5957064378548718872) -->
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
     <skip />
-    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (9055596817716471373) -->
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
     <skip />
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - ପ୍ରାୟ <xliff:g id="TIME">%2$s</xliff:g> ଅବଶିଷ୍ଟ ରହିଛି"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - ଆପଣଙ୍କ ବ୍ୟବହାରକୁ ଆଧାର କରି ପ୍ରାୟ <xliff:g id="TIME">%2$s</xliff:g> ଅବଶିଷ୍ଟ"</string>
-    <!-- no translation found for power_remaining_duration_shutdown_imminent (7679005631124015335) -->
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
     <skip />
-    <!-- no translation found for power_remaining_duration_shutdown_imminent (261050880878965621) -->
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
     <skip />
-    <!-- no translation found for power_remaining_duration_shutdown_imminent (2020049829798578618) -->
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
     <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"ସମ୍ପୂର୍ଣ୍ଣ ଚାର୍ଜ ହେବାପାଇଁ <xliff:g id="TIME">%1$s</xliff:g> ଅବଶିଷ୍ଟ ଅଛି"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ପୂର୍ଣ୍ଣ ଚାର୍ଜ ହେବା ପର୍ଯ୍ୟନ୍ତ"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"ଅଜ୍ଞାତ"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"ଚାର୍ଜ ହେଉଛି"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 6549861..2287d23 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"ਨਿੱਜੀ DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"ਨਿੱਜੀ DNS ਮੋਡ ਚੁਣੋ"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"ਬੰਦ"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"ਮੌਕਾਪ੍ਰਸਤ"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"ਨਿੱਜੀ DNS ਪ੍ਰਦਾਨਕ ਹੋਸਟਨਾਮ"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ਪ੍ਰਦਾਨਕ ਦਾ ਹੋਸਟਨਾਮ ਦਾਖਲ ਕਰੋ"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ਵਾਇਰਲੈੱਸ ਡਿਸਪਲੇ ਪ੍ਰਮਾਣੀਕਰਨ ਲਈ ਚੋਣਾਂ ਪ੍ਰਦਰਸ਼ਿਤ ਕਰੋ"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ਇਹ ਵਿਸ਼ੇਸ਼ਤਾ ਪ੍ਰਯੋਗਾਤਮਿਕ ਹੈ ਅਤੇ ਪ੍ਰਦਰਸ਼ਨ ਤੇ ਅਸਰ ਪਾ ਸਕਦੀ ਹੈ।"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ਦੁਆਰਾ ਓਵਰਰਾਈਡ ਕੀਤਾ"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"ਲਗਭਗ <xliff:g id="TIME">%1$s</xliff:g> ਬਾਕੀ"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"ਤੁਹਾਡੀ ਵਰਤੋਂ ਦੇ ਆਧਾਰ \'ਤੇ ਲਗਭਗ <xliff:g id="TIME">%1$s</xliff:g> ਬਾਕੀ"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"ਪੂਰੀ ਤਰ੍ਹਾਂ ਚਾਰਜ ਹੋਣ ਲਈ <xliff:g id="TIME">%1$s</xliff:g> ਬਾਕੀ"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> ਬਾਕੀ"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> ਤੋਂ ਘੱਟ ਸਮਾਂ ਬਾਕੀ"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g> ਤੋਂ ਘੱਟ ਸਮਾਂ ਬਾਕੀ"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g><xliff:g id="TIME_REMAINING">%2$s</xliff:g> ਤੋਂ ਵੱਧ ਸਮਾਂ ਬਾਕੀ"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ਤੋਂ ਵੱਧ ਸਮਾਂ ਬਾਕੀ"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ਫ਼ੋਨ ਛੇਤੀ ਹੀ ਬੰਦ ਹੋ ਸਕਦਾ ਹੈ"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ਟੈਬਲੈੱਟ ਛੇਤੀ ਹੀ ਬੰਦ ਹੋ ਸਕਦਾ ਹੈ"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"ਡੀਵਾਈਸ ਛੇਤੀ ਹੀ ਬੰਦ ਹੋ ਸਕਦਾ ਹੈ"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਲਗਭਗ <xliff:g id="TIME">%2$s</xliff:g> ਬਾਕੀ"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਤੁਹਾਡੀ ਵਰਤੋਂ ਦੇ ਆਧਾਰ \'ਤੇ ਲਗਭਗ <xliff:g id="TIME">%2$s</xliff:g> ਬਾਕੀ"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਫ਼ੋਨ ਛੇਤੀ ਹੀ ਬੰਦ ਹੋ ਸਕਦਾ ਹੈ"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਟੈਬਲੈੱਟ ਛੇਤੀ ਹੀ ਬੰਦ ਹੋ ਸਕਦਾ ਹੈ"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਡੀਵਾਈਸ ਛੇਤੀ ਹੀ ਬੰਦ ਹੋ ਸਕਦਾ ਹੈ"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"ਪੂਰੀ ਤਰ੍ਹਾਂ ਚਾਰਜ ਹੋਣ ਲਈ <xliff:g id="TIME">%1$s</xliff:g> ਬਾਕੀ"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"ਪੂਰੀ ਤਰ੍ਹਾਂ ਚਾਰਜ ਹੋਣ ਤੱਕ <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"ਅਗਿਆਤ"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index c7deb56..45c44c6 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Prywatny DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Wybierz tryb prywatnego DNS"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Wyłączony"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Oportunistyczny"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Nazwa hosta dostawcy prywatnego DNS"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Wpisz nazwę hosta dostawcy DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Pokaż opcje certyfikacji wyświetlacza bezprzewodowego"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"To jest funkcja eksperymentalna i może wpływać na działanie urządzenia."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Nadpisana przez <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Pozostało: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Jeszcze około <xliff:g id="TIME">%1$s</xliff:g> (na podstawie Twojego sposobu korzystania)"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> do pełnego naładowania"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Zostało <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Pozostało mniej niż <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – pozostało mniej niż <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – pozostało ponad <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"pozostało ponad <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefon może się wkrótce wyłączyć"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet może się wkrótce wyłączyć"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"urządzenie może się wkrótce wyłączyć"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – pozostało około <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – jeszcze około <xliff:g id="TIME">%2$s</xliff:g> (na podstawie Twojego sposobu korzystania)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – telefon może się wkrótce wyłączyć"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – tablet może się wkrótce wyłączyć"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – urządzenie może się wkrótce wyłączyć"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> do pełnego naładowania"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pełnego naładowania"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Nieznane"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Ładowanie"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 7693a54..bc9c82e 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -135,7 +135,7 @@
     <string name="tts_settings_title" msgid="1237820681016639683">"Conversão de texto em voz"</string>
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Taxa de fala"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocidade em que o texto é falado"</string>
-    <string name="tts_default_pitch_title" msgid="6135942113172488671">"Frequência do som"</string>
+    <string name="tts_default_pitch_title" msgid="6135942113172488671">"Tom da fala"</string>
     <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Afeta o tom da voz sintetizada"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Usar idioma do sistema"</string>
@@ -157,7 +157,7 @@
     <string name="tts_engine_settings_button" msgid="1030512042040722285">"Iniciar configurações do mecanismo"</string>
     <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Mecanismo preferencial"</string>
     <string name="tts_general_section_title" msgid="4402572014604490502">"Gerais"</string>
-    <string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"Redefinir a frequência do som da fala"</string>
+    <string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"Redefinir o tom da fala"</string>
     <string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"Redefinir o tom no qual o texto é falado para o padrão."</string>
   <string-array name="tts_rate_entries">
     <item msgid="6695494874362656215">"Muito devagar"</item>
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS particular"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Selecione o modo DNS particular"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Desativado"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Oportunista"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Nome do host do provedor de DNS particular"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Informe o nome do host do provedor de DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opções de certificação de Display sem fio"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Este recurso é experimental e pode afetar o desempenho."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Cerca de <xliff:g id="TIME">%1$s</xliff:g> restante(s)"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Cerca de <xliff:g id="TIME">%1$s</xliff:g> restante(s) com base no seu uso"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> restante(s) até a carga completa"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> restante(s)"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Menos de <xliff:g id="THRESHOLD">%1$s</xliff:g> restante(s)"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g>: menos de <xliff:g id="THRESHOLD">%2$s</xliff:g> restante(s)"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>mais de <xliff:g id="TIME_REMAINING">%2$s</xliff:g> restante(s)"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"mais de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> restante(s)"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"o smartphone pode ser desligado em breve"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"o tablet pode ser desligado em breve"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"o dispositivo pode ser desligado em breve"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - cerca de <xliff:g id="TIME">%2$s</xliff:g> restante(s)"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g>: cerca de <xliff:g id="TIME">%2$s</xliff:g> restante(s) com base no seu uso"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g>: o smartphone pode ser desligado em breve"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g>: o tablet pode ser desligado em breve"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g>: o dispositivo pode ser desligado em breve"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> restante(s) até a carga completa"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até a carga completa"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconhecido"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Carregando"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index a4987a1..5b2ad1d 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS privado"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Selecionar modo DNS privado"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Desativado"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Oportunista"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Nome de anfitrião do fornecedor DNS privado"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introduza o nome de anfitrião do fornecedor DNS."</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opções da certificação de display sem fios"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta funcionalidade é experimental e pode afetar o desempenho."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Falta(m) cerca de <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Resta(m) cerca de <xliff:g id="TIME">%1$s</xliff:g> com base na sua utilização"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Falta(m) <xliff:g id="TIME">%1$s</xliff:g> para concluir o carregamento"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Resta(m) <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Resta(m) menos de <xliff:g id="THRESHOLD">%1$s</xliff:g>."</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – Resta(m) menos de <xliff:g id="THRESHOLD">%2$s</xliff:g>."</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – Resta(m) mais de <xliff:g id="TIME_REMAINING">%2$s</xliff:g>."</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"Resta(m) mais de <xliff:g id="TIME_REMAINING">%1$s</xliff:g>."</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"O telemóvel poderá ser encerrado em breve."</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"O tablet poderá ser encerrado em breve."</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"O dispositivo poderá ser encerrado em breve."</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – falta(m) cerca de <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – resta(m) cerca de <xliff:g id="TIME">%2$s</xliff:g> com base na sua utilização"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – O telemóvel poderá ser encerrado em breve."</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – O tablet poderá ser encerrado em breve."</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – O dispositivo poderá ser encerrado em breve."</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Falta(m) <xliff:g id="TIME">%1$s</xliff:g> para concluir o carregamento"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até ficar totalmente carregada"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconhecido"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"A carregar"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 7693a54..bc9c82e 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -135,7 +135,7 @@
     <string name="tts_settings_title" msgid="1237820681016639683">"Conversão de texto em voz"</string>
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Taxa de fala"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocidade em que o texto é falado"</string>
-    <string name="tts_default_pitch_title" msgid="6135942113172488671">"Frequência do som"</string>
+    <string name="tts_default_pitch_title" msgid="6135942113172488671">"Tom da fala"</string>
     <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Afeta o tom da voz sintetizada"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Usar idioma do sistema"</string>
@@ -157,7 +157,7 @@
     <string name="tts_engine_settings_button" msgid="1030512042040722285">"Iniciar configurações do mecanismo"</string>
     <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Mecanismo preferencial"</string>
     <string name="tts_general_section_title" msgid="4402572014604490502">"Gerais"</string>
-    <string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"Redefinir a frequência do som da fala"</string>
+    <string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"Redefinir o tom da fala"</string>
     <string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"Redefinir o tom no qual o texto é falado para o padrão."</string>
   <string-array name="tts_rate_entries">
     <item msgid="6695494874362656215">"Muito devagar"</item>
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS particular"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Selecione o modo DNS particular"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Desativado"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Oportunista"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Nome do host do provedor de DNS particular"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Informe o nome do host do provedor de DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opções de certificação de Display sem fio"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Este recurso é experimental e pode afetar o desempenho."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Cerca de <xliff:g id="TIME">%1$s</xliff:g> restante(s)"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Cerca de <xliff:g id="TIME">%1$s</xliff:g> restante(s) com base no seu uso"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> restante(s) até a carga completa"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> restante(s)"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Menos de <xliff:g id="THRESHOLD">%1$s</xliff:g> restante(s)"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g>: menos de <xliff:g id="THRESHOLD">%2$s</xliff:g> restante(s)"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>mais de <xliff:g id="TIME_REMAINING">%2$s</xliff:g> restante(s)"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"mais de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> restante(s)"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"o smartphone pode ser desligado em breve"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"o tablet pode ser desligado em breve"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"o dispositivo pode ser desligado em breve"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - cerca de <xliff:g id="TIME">%2$s</xliff:g> restante(s)"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g>: cerca de <xliff:g id="TIME">%2$s</xliff:g> restante(s) com base no seu uso"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g>: o smartphone pode ser desligado em breve"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g>: o tablet pode ser desligado em breve"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g>: o dispositivo pode ser desligado em breve"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> restante(s) até a carga completa"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até a carga completa"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconhecido"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Carregando"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 1db376e..4af2ba15 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS privat"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Selectați modul DNS privat"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Dezactivat"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Oportunist"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Nume de gazdă al furnizorului de DNS privat"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introduceți numele de gazdă al furnizorului de DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Afișați opțiunile pentru certificarea Ecran wireless"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Această funcție este experimentală și poate afecta performanțele."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Valoare înlocuită de <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Timp rămas: aproximativ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"În baza utilizării, timpul aproximativ rămas este: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Timp rămas până la încărcarea completă: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Timp rămas: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"a mai rămas mai puțin de <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - a mai rămas mai puțin de <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> - a mai rămas mai mult de <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"a mai rămas mai mult de <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefonul să poate închide în curând"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tableta se poate închide în curând"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"dispozitivul se poate închide în curând"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - încă aproximativ <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – în baza utilizării, timpul aproximativ rămas este: <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - telefonul se poate închide în curând"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - tableta se poate închide în curând"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - dispozitivul se poate închide în curând"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Timp rămas până la încărcarea completă: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> până la încărcarea completă"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Necunoscut"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Se încarcă"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index be08b05..46d40aa 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Персональный DNS-сервер"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Выберите режим персонального DNS-сервера"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"ВЫКЛ"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Гибкий"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Имя хоста поставщика персонального DNS-сервера"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Введите имя хоста поставщика услуг DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Показывать параметры сертификации беспроводных мониторов"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Это экспериментальная функция, она может снизить производительность устройства."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Новая настройка: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Осталось примерно <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Осталось примерно <xliff:g id="TIME">%1$s</xliff:g> при текущем уровне использования"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Ещё <xliff:g id="TIME">%1$s</xliff:g> до полной зарядки"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Осталось: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Осталось менее <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"Уровень заряда батареи <xliff:g id="LEVEL">%1$s</xliff:g>. Осталось менее <xliff:g id="THRESHOLD">%2$s</xliff:g>."</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"Уровень заряда батареи <xliff:g id="LEVEL">%1$s</xliff:g>. Осталось более <xliff:g id="TIME_REMAINING">%2$s</xliff:g>."</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"Осталось более <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"телефон скоро завершит работу"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"планшет скоро завершит работу"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"устройство скоро завершит работу"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – осталось примерно <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> (осталось примерно <xliff:g id="TIME">%2$s</xliff:g> при текущем уровне использования)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"Уровень заряда батареи <xliff:g id="LEVEL">%1$s</xliff:g>. Телефон скоро завершит работу."</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"Уровень заряда батареи <xliff:g id="LEVEL">%1$s</xliff:g>. Планшет скоро завершит работу."</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"Уровень заряда батареи <xliff:g id="LEVEL">%1$s</xliff:g>. Устройство скоро завершит работу."</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Ещё <xliff:g id="TIME">%1$s</xliff:g> до полной зарядки"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Неизвестно"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Идет зарядка"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 7d63e47..1b387c3 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"පුද්ගලික DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"පුද්ගලික DNS ප්‍රකාරය තෝරන්න"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"ක්‍රියාවිරහිතයි"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"අවස්ථාවාදී"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"පුද්ගලික DNS සැපයුම්කරු සත්කාරක නම"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS සැපයුම්කරුගේ සත්කාරක නම ඇතුළු කරන්න"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"නොරැහැන් සංදර්ශක සහතිකය සඳහා විකල්ප පෙන්වන්න"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"මෙම විශේෂාංගය පරීක්ෂණාත්මක සහ ඇතැම් විට ක්‍රියාකාරිත්වයට බලපෑ හැක."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> මගින් ඉක්මවන ලදී"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"<xliff:g id="TIME">%1$s</xliff:g> පමණ ඉතිරියි"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"ඔබගේ භාවිතය මත පදනම්ව <xliff:g id="TIME">%1$s</xliff:g> පමණ ඉතිරිව ඇත"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"පූර්ණව ආරෝපණය වන තෙක් <xliff:g id="TIME">%1$s</xliff:g> ඉතිරියි"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"ඉතිරි <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g>ට වඩා අඩුවෙන් ඉතිරිව ඇත"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g>ට වඩා අඩුවෙන් ඉතිරිව ඇත"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g><xliff:g id="TIME_REMAINING">%2$s</xliff:g>ට වඩා වැඩියෙන් ඉතිරිව ඇත"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>ට වඩා වැඩියෙන් ඉතිරිව ඇත"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"දුරකථනය ඉක්මනින් වැසිය හැකිය"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ටැබ්ලට් උපාංගය ඉක්මනින් වැසිය හැකිය"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"උපාංගය ඉක්මනින් වැසිය හැකිය"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>ක් පමණ ඇත"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - ඔබගේ භාවිතය මත පදනම්ව <xliff:g id="TIME">%2$s</xliff:g> පමණ ඉතිරිව ඇත"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - දුරකථනය ඉක්මනින් වැසිය හැකිය"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - ටැබ්ලට් පරිගණකය ඉක්මනින් වැසිය හැකිය"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - උපාංගය ඉක්මනින් වැසිය හැකිය"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"පූර්ණව ආරෝපණය වන තෙක් <xliff:g id="TIME">%1$s</xliff:g> ඉතිරියි"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> සම්පූර්ණයෙන් ආරෝපණය වන තෙක්"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"නොදනී"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"ආරෝපණය වෙමින්"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index aa40fef..6502d1a 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Súkromné DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Výber súkromného režimu DNS"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Vypnuté"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Príležitostné"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Súkromný názov hostiteľa poskytovateľa DNS"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Zadajte názov hostiteľa poskytovateľa DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Zobraziť možnosti certifikácie bezdrôtového zobrazenia"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Funkcia je experimentálna a môže mať vplyv na výkonnosť."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Prekonané predvoľbou <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Približný zostávajúci čas: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Zostáva približne <xliff:g id="TIME">%1$s</xliff:g> v závislosti od intenzity využitia"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Zostávajúci čas do úplného nabitia: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Zostávajúci čas: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Zostáva menej ako <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – zostáva menej ako <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – zostáva viac ako <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"zostáva viac ako <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefón sa môže čoskoro vypnúť"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet sa môže čoskoro vypnúť"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"zariadenie sa môže čoskoro vypnúť"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – približný zostávajúci čas: <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – zostáva približne <xliff:g id="TIME">%2$s</xliff:g> v závislosti od intenzity využitia"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – telefón sa môže čoskoro vypnúť"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – tablet sa môže čoskoro vypnúť"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – zariadenie sa môže čoskoro vypnúť"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Zostávajúci čas do úplného nabitia: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Neznáme"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Nabíja sa"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 55e4308..10dcb4d 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Zasebni strežnik DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Izbira načina zasebnega strežnika DNS"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Izklopljeno"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Priložnostno"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Ime gostitelja pri ponudniku zasebnega strežnika DNS"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Vnesite ime gostitelja pri ponudniku strežnika DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Pokaži možnosti za potrdilo brezžičnega zaslona"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"To je preskusna funkcija in lahko vpliva na učinkovitost delovanja."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Preglasila nastavitev: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Še približno <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Glede na način uporabe imate na voljo še približno <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Še <xliff:g id="TIME">%1$s</xliff:g> do polne napolnjenosti"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Še <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Preostalo manj kot <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – preostalo manj kot <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – preostalo več kot <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"preostalo več kot <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefon se bo morda kmalu zaustavil"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablični računalnik se bo morda kmalu zaustavil"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"naprava se bo morda kmalu zaustavila"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – še približno <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – glede na način uporabe imate na voljo še približno <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – telefon se bo morda kmalu zaustavil"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – tablični računalnik se bo morda kmalu zaustavil"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – naprava se bo morda kmalu zaustavila"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Še <xliff:g id="TIME">%1$s</xliff:g> do polne napolnjenosti"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napolnjenosti"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Neznano"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Polnjenje"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 5524e2c..7387441 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS-ja private"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Zgjidh modalitetin e DNS-së private"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Joaktiv"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Oportunist"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Emri i pritësit të ofruesit të DNS-së private"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Fut emrin e pritësit të ofruesit të DNS-së"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Shfaq opsionet për certifikimin e ekranit valor"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ky funksion është eksperimental dhe mund të ndikojë në veprimtari."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Mbivendosur nga <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Rreth <xliff:g id="TIME">%1$s</xliff:g> të mbetura"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Rreth <xliff:g id="TIME">%1$s</xliff:g> të mbetura bazuar në përdorimin tënd"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> të mbetura deri në ngarkimin e plotë"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> të mbetura"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Më pak se <xliff:g id="THRESHOLD">%1$s</xliff:g> të mbetura"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Më pak se <xliff:g id="THRESHOLD">%2$s</xliff:g> të mbetura"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>më pak se <xliff:g id="TIME_REMAINING">%2$s</xliff:g> të mbetura"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"më shumë se <xliff:g id="TIME_REMAINING">%1$s</xliff:g> të mbetura"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefoni mund të fiket së shpejti"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tableti mund të fiket së shpejti"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"pajisja mund të fiket së shpejti"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - rreth <xliff:g id="TIME">%2$s</xliff:g> të mbetura"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - rreth <xliff:g id="TIME">%2$s</xliff:g> të mbetura bazuar në përdorimin tënd"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - telefoni mund të fiket së shpejti"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - tableti mund të fiket së shpejti"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - tableti mund të fiket së shpejti"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> të mbetura deri në ngarkimin e plotë"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> derisa të mbushet plotësisht"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"I panjohur"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Po ngarkohet"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index a01b0b6..c644eae 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Приватни DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Изаберите режим приватног DNS-а"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Искључено"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Оппортунистички"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Име хоста добављача услуге приватног DNS-а"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Унесите име хоста добављача услуге DNS-а"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Приказ опција за сертификацију бежичног екрана"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ова функција је експериментална и може да утиче на квалитет рада."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Замењује га <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Још око <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"На основу потрошње имате још отприлике <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> до потпуног пуњења"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Преостало време: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Преостало је мање од <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – преостало је мање од <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – преостало је више од <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"преостало је више од <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"телефон ће се ускоро искључити"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"таблет ће се ускоро искључити"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"уређај ће се ускоро искључити"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – остало је око <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – на основу потрошње имате још отприлике <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – телефон ће се ускоро искључити"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – таблет ће се ускоро искључити"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – уређај ће се ускоро искључити"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> до потпуног пуњења"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до потпуног пуњења"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Непознато"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Пуњење"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index d8c6e4d..44875f5 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Privat DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Välj läget Privat DNS"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Av"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Opportunistisk"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Värdnamn för leverantör av privat DNS"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Ange värdnamn för DNS-leverantör"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Visa certifieringsalternativ för Wi-Fi-skärmdelning"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Den här funktionen är experimentell och kan påverka prestandan."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Har åsidosatts av <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Cirka <xliff:g id="TIME">%1$s</xliff:g> återstår"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Cirka <xliff:g id="TIME">%1$s</xliff:g> kvar utifrån din användning"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Batteriet är fulladdat om <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> kvar"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Mindre än <xliff:g id="THRESHOLD">%1$s</xliff:g> återstår"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – Mindre än <xliff:g id="THRESHOLD">%2$s</xliff:g> återstår"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>mer än <xliff:g id="TIME_REMAINING">%2$s</xliff:g> återstår"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"mer än <xliff:g id="TIME_REMAINING">%1$s</xliff:g> återstår"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"mobilen kan stängas av snart"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"surfplattan kan stängas av snart"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"enheten kan stängas av snart"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – cirka <xliff:g id="TIME">%2$s</xliff:g> kvar"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – cirka <xliff:g id="TIME">%2$s</xliff:g> kvar utifrån din användning"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – mobilen kan stängas av snart"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – surfplattan kan stängas av snart"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – enheten kan stängas av snart"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Batteriet är fulladdat om <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tills det är fulladdat"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Okänd"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Laddar"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index fd91e5b..6305fde 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS ya Faragha"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Chagua Hali ya DNS ya Faragha"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Imezimwa"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Inayojitokeza"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Jina la mpangishi wa huduma za DNS ya faragha"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Weka jina la mpangishi wa huduma za DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Onyesha chaguo za cheti cha kuonyesha pasiwaya"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Kipengele hiki ni cha majaribio na huenda kikaathiri utendaji wa kifaa chako."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Imetanguliwa na <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Zimesalia takribani <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Takriban <xliff:g id="TIME">%1$s</xliff:g> zimesalia kulingana na matumizi yako"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Imebaki <xliff:g id="TIME">%1$s</xliff:g> chaji ijae"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Zimesalia <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Zimesalia chini ya <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Zimesalia chini ya <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> zimesalia zaidi ya <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"zimesalia zaidi ya <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"simu inakaribia kuzimika"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"kompyuta kibao inakaribia kuzimika"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"kifaa kinakaribia kuzimika"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - imesalia takribani <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - takriban <xliff:g id="TIME">%2$s</xliff:g> zimesalia kulingana na matumizi yako"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - simu inakaribia kuzimika"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - kompyuta kibao inakaribia kuzimika"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - kifaa kinakaribia kuzimika"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Imebaki <xliff:g id="TIME">%1$s</xliff:g> chaji ijae"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> hadi ijae chaji"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Haijulikani"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Inachaji"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index b417cfb..ff983b7 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -76,7 +76,7 @@
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ஆடியோ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ஆடியோ"</string>
     <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"செவித்துணைக் கருவி"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"செவித்துணைக் கருவியுடன் இணைக்கப்பட்டிருக்கும்போது"</string>
+    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"செவித்துணைக் கருவியுடன் இணைக்கப்பட்டிருக்கிறது"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"மீடியா ஆடியோவுடன் இணைக்கப்பட்டது"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"மொபைல் ஆடியோவுடன் இணைக்கப்பட்டது"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"கோப்பைப் பரிமாற்றும் சேவையகத்துடன் இணைக்கப்பட்டது"</string>
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"தனிப்பட்ட DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"தனிப்பட்ட DNS பயன்முறையைத் தேர்ந்தெடுக்கவும்"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"ஆஃப்"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"சந்தர்ப்பவாதம்"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"தனிப்பட்ட DNS வழங்குநரின் ஹோஸ்ட் பெயர்"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS வழங்குநரின் ஹோஸ்ட் பெயரை உள்ளிடவும்"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"வயர்லெஸ் காட்சி சான்றுக்கான விருப்பங்களைக் காட்டு"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"இது சோதனை முறையிலான அம்சம், இது செயல்திறனைப் பாதிக்கலாம்."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> மூலம் மேலெழுதப்பட்டது"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"கிட்டத்தட்ட <xliff:g id="TIME">%1$s</xliff:g> உள்ளது"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"உபயோகத்தின் அடிப்படையில் கிட்டத்தட்ட <xliff:g id="TIME">%1$s</xliff:g> மீதமுள்ளது"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"முழு சார்ஜாக <xliff:g id="TIME">%1$s</xliff:g> ஆகும்"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> மீதமுள்ளது"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g>க்கும் குறைவாகவே பயன்படுத்த முடியும்"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> பேட்டரி மட்டுமே உள்ளது, <xliff:g id="THRESHOLD">%2$s</xliff:g>க்கும் குறைவாகவே பயன்படுத்தமுடியும்"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"பேட்டரி <xliff:g id="LEVEL">%1$s</xliff:g> உள்ளது, <xliff:g id="TIME_REMAINING">%2$s</xliff:g>க்கு மேல் பயன்படுத்த முடியும்"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>க்கு மேல் பயன்படுத்த முடியும்"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"மொபைல் விரைவில் ஆஃப் ஆகக்கூடும்"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"டேப்லெட் விரைவில் ஆஃப் ஆகக்கூடும்"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"சாதனம் விரைவில் ஆஃப் ஆகக்கூடும்"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - கிட்டத்தட்ட <xliff:g id="TIME">%2$s</xliff:g> மீதமுள்ளது"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - உபயோகத்தின் அடிப்படையில் கிட்டத்தட்ட <xliff:g id="TIME">%2$s</xliff:g> மீதமுள்ளது"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - மொபைல் விரைவில் ஆஃப் ஆகக்கூடும்"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - டேப்லெட் விரைவில் ஆஃப் ஆகக்கூடும்"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - சாதனம் விரைவில் ஆஃப் ஆகக்கூடும்"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"முழு சார்ஜாக <xliff:g id="TIME">%1$s</xliff:g> ஆகும்"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - முழு சார்ஜாக <xliff:g id="TIME">%2$s</xliff:g> ஆகும்"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"அறியப்படாத"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"சார்ஜ் ஆகிறது"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 99a35a3..bccb11e 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"ప్రైవేట్ DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"ప్రైవేట్ DNS మోడ్‌ను ఎంచుకోండి"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"ఆఫ్"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"అవకాశవాదం"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"ప్రైవేట్ DNS ప్రదాత హోస్ట్‌పేరు"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ప్రదాత యొక్క హోస్ట్‌పేరును నమోదు చేయండి"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"వైర్‌లెస్ ప్రదర్శన సర్టిఫికెట్ కోసం ఎంపికలను చూపు"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ఈ లక్షణం ప్రయోగాత్మకమైనది మరియు పనితీరుపై ప్రభావం చూపవచ్చు."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ద్వారా భర్తీ చేయబడింది"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"మిగిలి ఉన్న సమయం, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"మీ వినియోగం ఆధారంగా సుమారు <xliff:g id="TIME">%1$s</xliff:g> సమయం మిగిలి ఉంది"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"పూర్తిగా ఛార్జ్ కావడానికి <xliff:g id="TIME">%1$s</xliff:g> పడుతుంది"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> మిగిలి ఉంది"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> కంటే తక్కువ సమయం మిగిలి ఉంది"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g> కంటే తక్కువ సమయం మిగిలి ఉంది"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g><xliff:g id="TIME_REMAINING">%2$s</xliff:g> కంటే ఎక్కువ సమయం మిగిలి ఉంది"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> కంటే ఎక్కువ సమయం మిగిలి ఉంది"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ఫోన్ త్వరలో షట్‌డౌన్ కావచ్చు"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"టాబ్లెట్ త్వరలో షట్‌డౌన్ కావచ్చు"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"పరికరం త్వరలో షట్‌డౌన్ కావచ్చు"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> పని చేస్తుంది"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - మీ వినియోగం ఆధారంగా సుమారు <xliff:g id="TIME">%2$s</xliff:g> సమయం మిగిలి ఉంది"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - ఫోన్ త్వరలో షట్‌డౌన్ కావచ్చు"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - టాబ్లెట్ త్వరలో షట్‌డౌన్ కావచ్చు"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - పరికరం త్వరలో షట్‌డౌన్ కావచ్చు"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"పూర్తిగా ఛార్జ్ కావడానికి <xliff:g id="TIME">%1$s</xliff:g> పడుతుంది"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>లో పూర్తిగా ఛార్జ్ అవుతుంది"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"తెలియదు"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"ఛార్జ్ అవుతోంది"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index aab479e..2cedcfcf 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS ส่วนตัว"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"เลือกโหมด DNS ส่วนตัว"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"ปิด"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"ที่ใช้โอกาส"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"ชื่อโฮสต์ของผู้ให้บริการ DNS ส่วนตัว"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"ป้อนชื่อโฮสต์ของผู้ให้บริการ DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"แสดงตัวเลือกสำหรับการรับรองการแสดงผล แบบไร้สาย"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ฟีเจอร์นี้เป็นแบบทดลองและอาจส่งผลต่อประสิทธิภาพการทำงาน"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"แทนที่โดย <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"อีกประมาณ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"เหลืออีกราว <xliff:g id="TIME">%1$s</xliff:g> ขึ้นอยู่กับการใช้งานของคุณ"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"อีก <xliff:g id="TIME">%1$s</xliff:g> จึงจะชาร์จเต็ม"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"เหลืออีก <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"เหลืออีกไม่ถึง <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - เหลืออีกไม่ถึง <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> - เหลือเวลามากกว่า <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"เหลือเวลามากกว่า <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"โทรศัพท์อาจปิดเครื่องในไม่ช้า"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"แท็บเล็ตอาจปิดเครื่องในไม่ช้า"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"อุปกรณ์อาจปิดเครื่องในไม่ช้า"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - เหลือเวลาประมาณ <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - เหลืออีกราว <xliff:g id="TIME">%2$s</xliff:g> ขึ้นอยู่กับการใช้งานของคุณ"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - โทรศัพท์อาจปิดเครื่องในไม่ช้า"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - แท็บเล็ตอาจปิดเครื่องในไม่ช้า"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - อุปกรณ์อาจปิดเครื่องในไม่ช้า"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"อีก <xliff:g id="TIME">%1$s</xliff:g> จึงจะชาร์จเต็ม"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> จนกว่าจะชาร์จเต็ม"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"ไม่ทราบ"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"กำลังชาร์จ"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 6403213..dd774d2 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Pribadong DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Pumili ng Pribadong DNS Mode"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Naka-off"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Oportunista"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Hostname ng provider ng pribadong DNS"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Ilagay ang hostname ng DNS provider"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Ipakita ang mga opsyon para sa certification ng wireless display"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ang feature na ito ay pinag-eeksperimentuhan at maaaring makaapekto sa performance."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Na-override ng <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Humigit-kumulang <xliff:g id="TIME">%1$s</xliff:g> ang natitira"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Humigit-kumulang <xliff:g id="TIME">%1$s</xliff:g> ang natitira batay sa iyong paggamit"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> ang natitira bago makumpleto ang charge"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> pa"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Wala nang <xliff:g id="THRESHOLD">%1$s</xliff:g> ang natitira"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Wala nang <xliff:g id="THRESHOLD">%2$s</xliff:g> ang natitira"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>may mahigit <xliff:g id="TIME_REMAINING">%2$s</xliff:g> pa"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"may mahigit <xliff:g id="TIME_REMAINING">%1$s</xliff:g> pa"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"malapit nang mag-shut down ang telepono"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"malapit nang mag-shut down ang tablet"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"malapit nang mag-shut down ang device"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - humigit-kumulang <xliff:g id="TIME">%2$s</xliff:g> pa ang natitira"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - humigit-kumulang <xliff:g id="TIME">%2$s</xliff:g> ang natitira batay sa iyong paggamit"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - malapit nang mag-shut down ang telepono"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - malapit nang mag-shut down ang tablet"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - malapit nang mag-shut down ang device"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> ang natitira bago makumpleto ang charge"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> hanggang sa makumpleto ang charge"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Hindi Kilala"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Nagcha-charge"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 9fdeb4a..21707f4 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Gizli DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Gizli DNS Modunu Seçin"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Kapalı"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Fırsatçı"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Gizli DNS sağlayıcının ana makine adı"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS sağlayıcının ana makine adını gir"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Kablosuz ekran sertifikası seçeneklerini göster"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Bu özellik deneyseldir ve performansı etkileyebilir."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> tarafından geçersiz kılındı"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Yaklaşık <xliff:g id="TIME">%1$s</xliff:g> kaldı"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Kullanımınıza dayalı olarak yaklaşık <xliff:g id="TIME">%1$s</xliff:g> kaldı"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Tam olarak şarj olmasına <xliff:g id="TIME">%1$s</xliff:g> kaldı"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> kaldı"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"En fazla <xliff:g id="THRESHOLD">%1$s</xliff:g> kaldı"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - En fazla <xliff:g id="THRESHOLD">%2$s</xliff:g> kaldı"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> - en az <xliff:g id="TIME_REMAINING">%2$s</xliff:g> kaldı"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"en az <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kaldı"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefon kısa süre içinde kapanabilir"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"tablet kısa süre içinde kapanabilir"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"cihaz kısa süre içinde kapanabilir"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - yaklaşık <xliff:g id="TIME">%2$s</xliff:g> kaldı"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - kullanımınıza dayalı olarak yaklaşık <xliff:g id="TIME">%2$s</xliff:g> kaldı"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - telefon kısa süre içinde kapanabilir"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - tablet kısa süre içinde kapanabilir"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - cihaz kısa süre içinde kapanabilir"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Tam olarak şarj olmasına <xliff:g id="TIME">%1$s</xliff:g> kaldı"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tam şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> kaldı"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Bilinmiyor"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Şarj oluyor"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 1c85633..d1e68e1 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Приватна DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Виберіть режим \"Приватна DNS\""</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Вимкнено"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Періодично доступно"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Ім’я хосту приватного постачальника послуг DNS"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Введіть ім’я хосту постачальника послуг DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Показати параметри сертифікації бездротового екрана"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Це експериментальна функція. Вона може вплинути на продуктивність."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Замінено на <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Залишилося близько <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"На основі використання залишилося близько <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"До повного зарядження залишилося <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Залишилося <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Залишилося менше ніж <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – залишилося менше ніж <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – залишилося більше ніж <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"залишилося більше ніж <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"телефон може невдовзі вимкнутися"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"планшет може невдовзі вимкнутися"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"пристрій може невдовзі вимкнутися"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – ще <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> – на основі використання залишилося близько <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – телефон може невдовзі вимкнутися"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – планшет може невдовзі вимкнутися"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – пристрій може невдовзі вимкнутися"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"До повного зарядження залишилося <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного заряду"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Невідомо"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Заряджається"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 7c221d7..82686bd 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"‏نجی DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"‏نجی DNS وضع منتخب کریں"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"آف"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"موقع پرست"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"‏نجی DNS فراہم کنندہ میزبان کا نام"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"‏DNS فراہم کنندہ کے میزبان کا نام درج کریں"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"وائرلیس ڈسپلے سرٹیفیکیشن کیلئے اختیارات دکھائیں"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"یہ خصوصیت تجرباتی ہے اور اس کی وجہ سے کاکردگی متاثر ہو سکتی ہے۔"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> کے ذریعہ منسوخ کردیا گیا"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"تقریبًا <xliff:g id="TIME">%1$s</xliff:g> باقی ہے"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"آپ کے استعمال کی بنیاد پر تقریباً <xliff:g id="TIME">%1$s</xliff:g> باقی ہے"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"پوری طرح چارج ہونے میں <xliff:g id="TIME">%1$s</xliff:g> باقی ہے"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> باقی ہے"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> سے کم باقی ہے"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="THRESHOLD">%2$s</xliff:g> سے کم باقی ہے"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> <xliff:g id="TIME_REMAINING">%2$s</xliff:g> سے زیادہ باقی ہے"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> سے زیادہ باقی ہے"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"فون جلد ہی بند ہو سکتا ہے"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ٹیبلیٹ جلد ہی بند ہو سکتا ہے"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"آلہ جلد ہی بند ہو سکتا ہے"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - تقریباً <xliff:g id="TIME">%2$s</xliff:g> باقی ہے"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - آپ کے استعمال کی بنیاد پر تقریباً <xliff:g id="TIME">%2$s</xliff:g> باقی ہے"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - فون جلد ہی بند ہو سکتا ہے"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - ٹیبلیٹ جلد ہی بند ہو سکتا ہے"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - آلہ جلد ہی بند ہو سکتا ہے"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"‎<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>‎"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"پوری طرح چارج ہونے میں <xliff:g id="TIME">%1$s</xliff:g> باقی ہے"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> پوری طرح چارج ہونے تک"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"نامعلوم"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"چارج ہو رہا ہے"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 725d92f..4043e98 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"Shaxsiy DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Shaxsiy DNS rejimini tanlang"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"O‘chiq"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Moslashuvchan"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Shaxsiy DNS provayderining host nomi"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS provayderining host nomini kiriting"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Simsiz monitorlarni sertifikatlash parametrini ko‘rsatish"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Bu funksiya tajribaviy bo‘lib, u qurilma unumdorligiga ta’sir qilishi mumkin."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> bilan almashtirildi"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Taxminan <xliff:g id="TIME">%1$s</xliff:g> qoldi"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Joriy holatda taxminan <xliff:g id="TIME">%1$s</xliff:g> qoldi"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"To‘lishiga <xliff:g id="TIME">%1$s</xliff:g> qoldi"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> qoldi"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g>dan kamroq vaqt qoldi"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="THRESHOLD">%2$s</xliff:g>dan kamroq vaqt qoldi"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME_REMAINING">%2$s</xliff:g>dan ko‘proq vaqt qoldi"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>dan ko‘proq vaqt qoldi"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"telefon tez orada o‘chib qolishi mumkin"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"planshet tez orada o‘chib qolishi mumkin"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"qurilma tez orada o‘chib qolishi mumkin"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – taxminan <xliff:g id="TIME">%2$s</xliff:g> qoldi"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> (joriy holatda taxminan <xliff:g id="TIME">%2$s</xliff:g> qoldi)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> – telefon tez orada o‘chib qolishi mumkin"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> – planshet tez orada o‘chib qolishi mumkin"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> – qurilma tez orada o‘chib qolishi mumkin"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"To‘lishiga <xliff:g id="TIME">%1$s</xliff:g> qoldi"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> ichida to‘ladi"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Noma’lum"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Quvvat olmoqda"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 74bac0a..f05a1a8 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS riêng tư"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Chọn chế độ DNS riêng tư"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Tắt"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Cơ hội"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Tên máy chủ của nhà cung cấp DNS riêng tư"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Nhập tên máy chủ của nhà cung cấp DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Hiển thị tùy chọn chứng nhận hiển thị không dây"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Tính năng này là tính năng thử nghiệm và có thể ảnh hưởng đến hoạt động."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Bị ghi đè bởi <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Còn khoảng <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Còn khoảng <xliff:g id="TIME">%1$s</xliff:g> dựa trên mức sử dụng của bạn"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Còn <xliff:g id="TIME">%1$s</xliff:g> cho tới khi được sạc đầy"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Còn lại <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Còn lại không đến <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Còn lại không đến <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> còn lại hơn <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"còn lại hơn <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"điện thoại có thể sắp tắt"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"máy tính bảng có thể sắp tắt"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"thiết bị có thể sắp tắt"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - còn khoảng <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - còn khoảng <xliff:g id="TIME">%2$s</xliff:g> dựa trên mức sử dụng của bạn"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - điện thoại có thể sắp tắt"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - máy tính bảng có thể sắp tắt"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - thiết bị có thể sắp tắt"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Còn <xliff:g id="TIME">%1$s</xliff:g> cho tới khi được sạc đầy"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> cho tới khi được sạc đầy"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Không xác định"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Đang sạc"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 3590ace..8c2342e 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"私人 DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"选择私人 DNS 模式"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"关闭"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"随机"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"私人 DNS 提供商主机名"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"输入 DNS 提供商的主机名"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"显示无线显示认证选项"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"这是实验性功能,性能可能不稳定。"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"已被“<xliff:g id="TITLE">%1$s</xliff:g>”覆盖"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"还剩大约 <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"根据您的使用情况,大约还可使用 <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"还需 <xliff:g id="TIME">%1$s</xliff:g>充满电"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"还可用 <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"剩余电池续航时间不到 <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - 剩余电池续航时间不到 <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> - 剩余电池续航时间超过 <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"剩余电池续航时间超过 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"手机可能即将关机"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"平板电脑可能即将关机"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"设备可能即将关机"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - 大约还剩 <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - 根据您的使用情况,大约还可使用 <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - 手机可能即将关机"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - 平板电脑可能即将关机"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - 设备可能即将关机"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"还需 <xliff:g id="TIME">%1$s</xliff:g>充满电"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还需 <xliff:g id="TIME">%2$s</xliff:g>充满"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"未知"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"正在充电"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index f2162f4..6f03f0b 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"不公開的網域名稱系統 (DNS)"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"選取不公開的網域名稱系統 (DNS) 模式"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"停用"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"隨機"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"不公開的網域名稱系統 (DNS) 供應商主機名稱"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"輸入網域名稱系統 (DNS) 供應商的主機名稱"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"顯示無線螢幕分享認證的選項"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"這是實驗性功能,效能尚待改善。"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"已由「<xliff:g id="TITLE">%1$s</xliff:g>」覆寫"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"剩餘約 <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"根據您的使用情況,剩餘約 <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g>後就能充滿電"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"尚餘 <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"剩餘電量時間少於 <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - 剩餘電量時間少於 <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> - 剩餘電量時間超過 <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"剩餘電量時間超過 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"手機可能即將關機"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"平板電腦可能即將關機"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"裝置可能即將關機"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - 剩餘約 <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - 根據您的使用情況,剩餘約 <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - 手機可能即將關機"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - 平板電腦可能即將關機"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - 裝置可能即將關機"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g>後就能充滿電"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - 還需 <xliff:g id="TIME">%2$s</xliff:g>才能充滿電"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"未知"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"充電中"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index fa3001a..9856879 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"私人 DNS"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"選取私人 DNS 模式"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"停用"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"隨機"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"私人 DNS 供應商主機名稱"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"輸入 DNS 供應商的主機名稱"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"顯示無線螢幕分享認證的選項"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"這是一項實驗性功能,可能會對效能造成影響。"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"已改為<xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"還有大約 <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"根據你的使用情形,剩餘時間大約還有 <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"再過 <xliff:g id="TIME">%1$s</xliff:g>就能完成充電"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"還剩 <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"電池可用時間不到 <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - 電池可用時間不到 <xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g> - 電池可用時間超過 <xliff:g id="TIME_REMAINING">%2$s</xliff:g>"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"電池可用時間超過 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"手機可能即將關機"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"平板電腦可能即將關機"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"裝置可能即將關機"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - 約剩 <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - 根據你的使用情形,剩餘時間大約還有 <xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - 手機可能即將關機"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - 平板電腦可能即將關機"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - 裝置可能即將關機"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"再過 <xliff:g id="TIME">%1$s</xliff:g>就能完成充電"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"不明"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"充電中"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 5a4180c..64861ec 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -220,7 +220,8 @@
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"I-DNS eyimfihlo"</string>
     <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Khetha imodi ye-DNS eyimfihlo"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Kuvaliwe"</string>
-    <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Amathuba"</string>
+    <!-- no translation found for private_dns_mode_opportunistic (8314986739896927399) -->
+    <skip />
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Igama lomsingathi womhlinzeki we-DNS"</string>
     <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Faka igama lomsingathi womhlinzeki we-DNS"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Bonisa izinketho zokunikeza isitifiketi ukubukeka okungenantambo"</string>
@@ -356,22 +357,41 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Lesi sici esesilingo futhi singathinta ukusebenza."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Igitshezwe ngaphezulu yi-<xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"Cishe u-<xliff:g id="TIME">%1$s</xliff:g> osele"</string>
+    <!-- no translation found for power_discharging_duration (6655472132189365839) -->
+    <skip />
     <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"Cishe kusele okungu-<xliff:g id="TIME">%1$s</xliff:g> kusukela ekusetshenzisweni kwakho"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> kushiywe ishaja"</string>
+    <!-- no translation found for power_discharging_duration_enhanced (5726302316642148671) -->
+    <skip />
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> esisele"</string>
+    <!-- no translation found for power_discharge_by_enhanced (8788299408879961465) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only_enhanced (7692297898877104416) -->
+    <skip />
+    <!-- no translation found for power_discharge_by (6427074755635635749) -->
+    <skip />
+    <!-- no translation found for power_discharge_by_only (5888058889261108064) -->
+    <skip />
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Kusele okungaphansi kunokungu-<xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
-    <string name="power_remaining_less_than_duration" msgid="7967078125657859046">"<xliff:g id="LEVEL">%1$s</xliff:g> - Kusele okungaphansi kokungu<xliff:g id="THRESHOLD">%2$s</xliff:g>"</string>
-    <string name="power_remaining_more_than_subtext" msgid="6846716609975752316">"<xliff:g id="LEVEL">%1$s</xliff:g>ngaphezu kokungu-<xliff:g id="TIME_REMAINING">%2$s</xliff:g> okusele"</string>
-    <string name="power_remaining_only_more_than_subtext" msgid="8884488700395194194">"ngaphezulu kokungu-<xliff:g id="TIME_REMAINING">%1$s</xliff:g> okusele"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="8168317165722752881">"ifoni ingacisha maduze"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="5957064378548718872">"ithebulethi ingacisha maduze"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="9055596817716471373">"idivayisi ingacisha maduze"</string>
-    <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - cishe ngu-<xliff:g id="TIME">%2$s</xliff:g> osele"</string>
-    <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">%1$s</xliff:g> - cishe ngu-<xliff:g id="TIME">%2$s</xliff:g> osele kusukela ekusetshenzisweni kwakho"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="7679005631124015335">"<xliff:g id="LEVEL">%1$s</xliff:g> - ifoni ingacisha maduze"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="261050880878965621">"<xliff:g id="LEVEL">%1$s</xliff:g> - ithebulethi ingacisha maduze"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="2020049829798578618">"<xliff:g id="LEVEL">%1$s</xliff:g> - idivayisi ingacisha maduze"</string>
+    <!-- no translation found for power_remaining_less_than_duration (5751885147712659423) -->
+    <skip />
+    <!-- no translation found for power_remaining_more_than_subtext (3176771815132876675) -->
+    <skip />
+    <!-- no translation found for power_remaining_only_more_than_subtext (8931654680569617380) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1181059207608751924) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2606370266981054691) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (2918084807716859985) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (3090926004324573908) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7466484148515796216) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (603933521600231649) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> kushiywe ishaja"</string>
     <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> kuze ligcwale ngokuphelele"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Akwaziwa"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Iyashaja"</string>
diff --git a/packages/SystemUI/res/layout/signal_cluster_view.xml b/packages/SystemUI/res/layout/signal_cluster_view.xml
index 25c87d3..cfa372b 100644
--- a/packages/SystemUI/res/layout/signal_cluster_view.xml
+++ b/packages/SystemUI/res/layout/signal_cluster_view.xml
@@ -115,27 +115,6 @@
         android:layout_width="wrap_content"
         >
     </LinearLayout>
-    <FrameLayout
-        android:id="@+id/no_sims_combo"
-        android:layout_height="wrap_content"
-        android:layout_width="wrap_content"
-        android:contentDescription="@string/accessibility_no_sims">
-        <com.android.systemui.statusbar.AlphaOptimizedImageView
-            android:theme="?attr/lightIconTheme"
-            android:id="@+id/no_sims"
-            android:layout_height="wrap_content"
-            android:layout_width="wrap_content"
-            android:src="@drawable/stat_sys_no_sims"
-            />
-        <com.android.systemui.statusbar.AlphaOptimizedImageView
-            android:theme="?attr/darkIconTheme"
-            android:id="@+id/no_sims_dark"
-            android:layout_height="wrap_content"
-            android:layout_width="wrap_content"
-            android:src="@drawable/stat_sys_no_sims"
-            android:alpha="0.0"
-            />
-    </FrameLayout>
     <View
         android:id="@+id/wifi_airplane_spacer"
         android:layout_width="@dimen/status_bar_airplane_spacer_width"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index e506d2f..8cb68c0 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -468,7 +468,7 @@
     <string name="accessibility_casting">@string/quick_settings_casting</string>
 
     <!-- Content description of the work mode icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_work_mode">@string/quick_settings_work_mode_on_label</string>
+    <string name="accessibility_work_mode">@string/quick_settings_work_mode_label</string>
 
     <!-- Content description to tell the user that this button will remove an application from recents -->
     <string name="accessibility_recents_item_will_be_dismissed">Dismiss <xliff:g id="app" example="Calendar">%s</xliff:g>.</string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
index 5b49e67..a9c80c6 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
@@ -109,4 +109,16 @@
             Log.w(TAG, "Failed to end prolonged animations: ", e);
         }
     }
+
+    /**
+     * Enable or disable haptic feedback on the navigation bar buttons.
+     */
+    public void setNavBarVirtualKeyHapticFeedbackEnabled(boolean enabled) {
+        try {
+            WindowManagerGlobal.getWindowManagerService()
+                    .setNavBarVirtualKeyHapticFeedbackEnabled(enabled);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to enable or disable navigation bar button haptics: ", e);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
index 3c666e4..041af0e 100644
--- a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
@@ -36,6 +36,7 @@
 import com.android.systemui.OverviewProxyService.OverviewProxyListener;
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.DockedFirstAnimationFrameEvent;
+import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.shared.recents.ISystemUiProxy;
 import com.android.systemui.shared.system.GraphicBufferCompat;
@@ -201,15 +202,18 @@
         mConnectionBackoffAttempts = 0;
         mLauncherComponentName = ComponentName
                 .unflattenFromString(context.getString(R.string.config_overviewServiceComponent));
-        mDeviceProvisionedController.addCallback(mDeviceProvisionedCallback);
 
         // Listen for the package update changes.
-        IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
-        filter.addDataScheme("package");
-        filter.addDataSchemeSpecificPart(mLauncherComponentName.getPackageName(),
-                PatternMatcher.PATTERN_LITERAL);
-        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
-        mContext.registerReceiver(mLauncherAddedReceiver, filter);
+        if (SystemServicesProxy.getInstance(context)
+                .isSystemUser(mDeviceProvisionedController.getCurrentUser())) {
+            mDeviceProvisionedController.addCallback(mDeviceProvisionedCallback);
+            IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
+            filter.addDataScheme("package");
+            filter.addDataSchemeSpecificPart(mLauncherComponentName.getPackageName(),
+                    PatternMatcher.PATTERN_LITERAL);
+            filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+            mContext.registerReceiver(mLauncherAddedReceiver, filter);
+        }
     }
 
     public void startConnectionToCurrentUser() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
index 8593249..5bab3e8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
@@ -21,12 +21,11 @@
 import android.service.quicksettings.Tile;
 import android.widget.Switch;
 
-import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.qs.QSHost;
 import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.phone.ManagedProfileController;
 
@@ -83,11 +82,15 @@
 
     @Override
     public CharSequence getTileLabel() {
-        return mContext.getString(R.string.quick_settings_work_mode_on_label);
+        return mContext.getString(R.string.quick_settings_work_mode_label);
     }
 
     @Override
     protected void handleUpdateState(BooleanState state, Object arg) {
+        if (!isAvailable()) {
+            onManagedProfileRemoved();
+        }
+
         if (state.slash == null) {
             state.slash = new SlashState();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index cb6e5a6..0f5e71e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -73,9 +73,7 @@
     private final NetworkController mNetworkController;
     private final SecurityController mSecurityController;
 
-    private boolean mNoSimsVisible = false;
     private boolean mVpnVisible = false;
-    private boolean mSimDetected;
     private int mVpnIconId = 0;
     private int mLastVpnIconId = -1;
     private boolean mEthernetVisible = false;
@@ -86,7 +84,6 @@
     private int mLastWifiStrengthId = -1;
     private boolean mWifiIn;
     private boolean mWifiOut;
-    private int mLastWifiActivityId = -1;
     private boolean mIsAirplaneMode = false;
     private int mAirplaneIconId = 0;
     private int mLastAirplaneIconId = -1;
@@ -99,8 +96,7 @@
     private final Rect mTintArea = new Rect();
 
     ViewGroup mEthernetGroup, mWifiGroup;
-    View mNoSimsCombo;
-    ImageView mVpn, mEthernet, mWifi, mAirplane, mNoSims, mEthernetDark, mWifiDark, mNoSimsDark;
+    ImageView mVpn, mEthernet, mWifi, mAirplane, mEthernetDark, mWifiDark;
     ImageView mWifiActivityIn;
     ImageView mWifiActivityOut;
     View mWifiAirplaneSpacer;
@@ -203,9 +199,6 @@
         mWifiActivityIn = findViewById(R.id.wifi_in);
         mWifiActivityOut= findViewById(R.id.wifi_out);
         mAirplane       = findViewById(R.id.airplane);
-        mNoSims         = findViewById(R.id.no_sims);
-        mNoSimsDark     = findViewById(R.id.no_sims_dark);
-        mNoSimsCombo    =             findViewById(R.id.no_sims_combo);
         mWifiAirplaneSpacer =         findViewById(R.id.wifi_airplane_spacer);
         mWifiSignalSpacer =           findViewById(R.id.wifi_signal_spacer);
         mMobileSignalGroup =          findViewById(R.id.mobile_signal_group);
@@ -224,11 +217,6 @@
         }
 
         mVpn.setImageDrawable(new ScalingDrawableWrapper(mVpn.getDrawable(), mIconScaleFactor));
-
-        mNoSims.setImageDrawable(
-                new ScalingDrawableWrapper(mNoSims.getDrawable(), mIconScaleFactor));
-        mNoSimsDark.setImageDrawable(
-                new ScalingDrawableWrapper(mNoSimsDark.getDrawable(), mIconScaleFactor));
     }
 
     @Override
@@ -333,9 +321,7 @@
 
     @Override
     public void setNoSims(boolean show, boolean simDetected) {
-        mNoSimsVisible = show && !mBlockMobile;
-        mSimDetected = simDetected;
-        apply();
+        // Noop. Status bar no longer shows no sim icon.
     }
 
     @Override
@@ -545,38 +531,13 @@
             mWifiAirplaneSpacer.setVisibility(View.GONE);
         }
 
-        if (((anyMobileVisible && firstMobileTypeId != 0) || mNoSimsVisible) && mWifiVisible) {
+        if ((anyMobileVisible && firstMobileTypeId != 0) && mWifiVisible) {
             mWifiSignalSpacer.setVisibility(View.VISIBLE);
         } else {
             mWifiSignalSpacer.setVisibility(View.GONE);
         }
 
-        if (mNoSimsVisible) {
-            mIconLogger.onIconShown(SLOT_MOBILE);
-            mNoSimsCombo.setVisibility(View.VISIBLE);
-            if (!Objects.equals(mSimDetected, mNoSimsCombo.getTag())) {
-                mNoSimsCombo.setTag(mSimDetected);
-                if (mSimDetected) {
-                    SignalDrawable d = new SignalDrawable(mNoSims.getContext());
-                    d.setDarkIntensity(0);
-                    mNoSims.setImageDrawable(d);
-                    mNoSims.setImageLevel(SignalDrawable.getEmptyState(4));
-
-                    SignalDrawable dark = new SignalDrawable(mNoSims.getContext());
-                    dark.setDarkIntensity(1);
-                    mNoSimsDark.setImageDrawable(dark);
-                    mNoSimsDark.setImageLevel(SignalDrawable.getEmptyState(4));
-                } else {
-                    mNoSims.setImageResource(R.drawable.stat_sys_no_sims);
-                    mNoSimsDark.setImageResource(R.drawable.stat_sys_no_sims);
-                }
-            }
-        } else {
-            mIconLogger.onIconHidden(SLOT_MOBILE);
-            mNoSimsCombo.setVisibility(View.GONE);
-        }
-
-        boolean anythingVisible = mNoSimsVisible || mWifiVisible || mIsAirplaneMode
+        boolean anythingVisible = mWifiVisible || mIsAirplaneMode
                 || anyMobileVisible || mVpnVisible || mEthernetVisible;
         setPaddingRelative(0, 0, anythingVisible ? mEndPadding : mEndPaddingNothingVisible, 0);
     }
@@ -613,9 +574,6 @@
         setTint(mVpn, DarkIconDispatcher.getTint(mTintArea, mVpn, mIconTint));
         setTint(mAirplane, DarkIconDispatcher.getTint(mTintArea, mAirplane, mIconTint));
         applyDarkIntensity(
-                DarkIconDispatcher.getDarkIntensity(mTintArea, mNoSims, mDarkIntensity),
-                mNoSims, mNoSimsDark);
-        applyDarkIntensity(
                 DarkIconDispatcher.getDarkIntensity(mTintArea, mWifi, mDarkIntensity),
                 mWifi, mWifiDark);
         setTint(mWifiActivityIn,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 0ed69e6..da042d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -46,7 +46,6 @@
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.drawable.AnimatedVectorDrawable;
-import android.graphics.drawable.Drawable;
 import android.inputmethodservice.InputMethodService;
 import android.os.Binder;
 import android.os.Bundle;
@@ -88,6 +87,7 @@
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.WindowManagerWrapper;
 import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.CommandQueue.Callbacks;
@@ -165,6 +165,8 @@
         public void onConnectionChanged(boolean isConnected) {
             mNavigationBarView.onOverviewProxyConnectionChanged(isConnected);
             updateScreenPinningGestures();
+            WindowManagerWrapper.getInstance()
+                    .setNavBarVirtualKeyHapticFeedbackEnabled(!isConnected);
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index d8d388c..e59a6b5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -18,7 +18,6 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
-import android.animation.PropertyValuesHolder;
 import android.animation.ValueAnimator;
 import android.app.AlarmManager;
 import android.app.WallpaperManager;
@@ -72,10 +71,6 @@
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     public static final long ANIMATION_DURATION = 220;
-    public static final Interpolator KEYGUARD_FADE_OUT_INTERPOLATOR
-            = new PathInterpolator(0f, 0, 0.7f, 1f);
-    public static final Interpolator KEYGUARD_FADE_OUT_INTERPOLATOR_LOCKED
-            = new PathInterpolator(0.3f, 0f, 0.8f, 1f);
 
     /**
      * When both scrims have 0 alpha.
@@ -144,7 +139,6 @@
     protected boolean mAnimateChange;
     private boolean mUpdatePending;
     private boolean mTracking;
-    private boolean mAnimateKeyguardFadingOut;
     protected long mAnimationDuration = -1;
     private long mAnimationDelay;
     private Runnable mOnAnimationFinished;
@@ -158,8 +152,6 @@
     private int mPinnedHeadsUpCount;
     private float mTopHeadsUpDragAmount;
     private View mDraggedHeadsUpView;
-    private boolean mKeyguardFadingOutInProgress;
-    private ValueAnimator mKeyguardFadeoutAnimation;
     private int mScrimsVisibility;
     private final Consumer<Integer> mScrimVisibleListener;
     private boolean mBlankScreen;
@@ -269,10 +261,6 @@
         // to do the same when you're just showing the brightness mirror.
         mNeedsDrawableColorUpdate = state != ScrimState.BRIGHTNESS_MIRROR;
 
-        if (mKeyguardFadeoutAnimation != null) {
-            mKeyguardFadeoutAnimation.cancel();
-        }
-
         // The device might sleep if it's entering AOD, we need to make sure that
         // the animation plays properly until the last frame.
         // It's important to avoid holding the wakelock unless necessary because
@@ -362,7 +350,7 @@
      *
      * The expansion fraction is tied to the scrim opacity.
      *
-     * @param fraction From 0 to 1 where 0 means collapse and 1 expanded.
+     * @param fraction From 0 to 1 where 0 means collapsed and 1 expanded.
      */
     public void setPanelExpansion(float fraction) {
         if (mExpansionFraction != fraction) {
@@ -381,8 +369,25 @@
             if (mPinnedHeadsUpCount != 0) {
                 updateHeadsUpScrim(false);
             }
-            updateScrim(false /* animate */, mScrimInFront, mCurrentInFrontAlpha);
-            updateScrim(false /* animate */, mScrimBehind, mCurrentBehindAlpha);
+
+            setOrAdaptCurrentAnimation(mScrimBehind);
+            setOrAdaptCurrentAnimation(mScrimInFront);
+        }
+    }
+
+    private void setOrAdaptCurrentAnimation(View scrim) {
+        if (!isAnimating(scrim)) {
+            updateScrimColor(scrim, getCurrentScrimAlpha(scrim), getCurrentScrimTint(scrim));
+        } else {
+            ValueAnimator previousAnimator = (ValueAnimator) scrim.getTag(TAG_KEY_ANIM);
+            float alpha = getCurrentScrimAlpha(scrim);
+            float previousEndValue = (Float) scrim.getTag(TAG_END_ALPHA);
+            float previousStartValue = (Float) scrim.getTag(TAG_START_ALPHA);
+            float relativeDiff = alpha - previousEndValue;
+            float newStartValue = previousStartValue + relativeDiff;
+            scrim.setTag(TAG_START_ALPHA, newStartValue);
+            scrim.setTag(TAG_END_ALPHA, alpha);
+            previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
         }
     }
 
@@ -523,14 +528,14 @@
         setScrimAlpha(mScrimInFront, alpha);
     }
 
-    private void setScrimAlpha(View scrim, float alpha) {
+    private void setScrimAlpha(ScrimView scrim, float alpha) {
         if (alpha == 0f) {
             scrim.setClickable(false);
         } else {
             // Eat touch events (unless dozing).
             scrim.setClickable(!(mState == ScrimState.AOD));
         }
-        updateScrim(mAnimateChange, scrim, alpha);
+        updateScrim(scrim, alpha);
     }
 
     private void updateScrimColor(View scrim, float alpha, int tint) {
@@ -554,41 +559,27 @@
         dispatchScrimsVisible();
     }
 
-    private int getCurrentScrimTint(View scrim) {
-        return scrim == mScrimInFront ? mCurrentInFrontTint : mCurrentBehindTint;
-    }
-
     private void startScrimAnimation(final View scrim, float current) {
         ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
         final int initialScrimTint = scrim instanceof ScrimView ? ((ScrimView) scrim).getTint() :
                 Color.TRANSPARENT;
         anim.addUpdateListener(animation -> {
+            final float startAlpha = (Float) scrim.getTag(TAG_START_ALPHA);
             final float animAmount = (float) animation.getAnimatedValue();
-            final int finalScrimTint = scrim == mScrimInFront ?
-                    mCurrentInFrontTint : mCurrentBehindTint;
-            float finalScrimAlpha = scrim == mScrimInFront ?
-                    mCurrentInFrontAlpha : mCurrentBehindAlpha;
-            float alpha = MathUtils.lerp(current, finalScrimAlpha, animAmount);
+            final int finalScrimTint = getCurrentScrimTint(scrim);
+            final float finalScrimAlpha = getCurrentScrimAlpha(scrim);
+            float alpha = MathUtils.lerp(startAlpha, finalScrimAlpha, animAmount);
+            alpha = MathUtils.constrain(alpha, 0f, 1f);
             int tint = ColorUtils.blendARGB(initialScrimTint, finalScrimTint, animAmount);
             updateScrimColor(scrim, alpha, tint);
             dispatchScrimsVisible();
         });
-        anim.setInterpolator(getInterpolator());
+        anim.setInterpolator(mInterpolator);
         anim.setStartDelay(mAnimationDelay);
         anim.setDuration(mAnimationDuration);
         anim.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
-                final int finalScrimTint = scrim == mScrimInFront ?
-                        mCurrentInFrontTint : mCurrentBehindTint;
-                float finalScrimAlpha = scrim == mScrimInFront ?
-                        mCurrentInFrontAlpha : mCurrentBehindAlpha;
-                updateScrimColor(scrim, finalScrimAlpha, finalScrimTint);
-
-                if (mKeyguardFadingOutInProgress) {
-                    mKeyguardFadeoutAnimation = null;
-                    mKeyguardFadingOutInProgress = false;
-                }
                 onFinished();
 
                 scrim.setTag(TAG_KEY_ANIM, null);
@@ -600,21 +591,37 @@
                 }
             }
         });
-        anim.start();
-        if (mAnimateKeyguardFadingOut) {
-            mKeyguardFadingOutInProgress = true;
-            mKeyguardFadeoutAnimation = anim;
-        }
+
+        // Cache alpha values because we might want to update this animator in the future if
+        // the user expands the panel while the animation is still running.
+        scrim.setTag(TAG_START_ALPHA, current);
+        scrim.setTag(TAG_END_ALPHA, getCurrentScrimAlpha(scrim));
+
         scrim.setTag(TAG_KEY_ANIM, anim);
+        anim.start();
     }
 
-    protected Interpolator getInterpolator() {
-        if (mAnimateKeyguardFadingOut && mKeyguardUpdateMonitor.needsSlowUnlockTransition()) {
-            return KEYGUARD_FADE_OUT_INTERPOLATOR_LOCKED;
-        } else if (mAnimateKeyguardFadingOut) {
-            return KEYGUARD_FADE_OUT_INTERPOLATOR;
+    private float getCurrentScrimAlpha(View scrim) {
+        if (scrim == mScrimInFront) {
+            return mCurrentInFrontAlpha;
+        } else if (scrim == mScrimBehind) {
+            return mCurrentBehindAlpha;
+        } else if (scrim == mHeadsUpScrim) {
+            return calculateHeadsUpAlpha();
         } else {
-            return mInterpolator;
+            throw new IllegalArgumentException("Unknown scrim view");
+        }
+    }
+
+    private int getCurrentScrimTint(View scrim) {
+        if (scrim == mScrimInFront) {
+            return mCurrentInFrontTint;
+        } else if (scrim == mScrimBehind) {
+            return mCurrentBehindTint;
+        } else if (scrim == mHeadsUpScrim) {
+            return Color.TRANSPARENT;
+        } else {
+            throw new IllegalArgumentException("Unknown scrim view");
         }
     }
 
@@ -626,9 +633,11 @@
             mCallback.onStart();
         }
         updateScrims();
-
-        // Make sure that we always call the listener even if we didn't start an animation.
-        endAnimateKeyguardFadingOut(false /* force */);
+        if (mOnAnimationFinished != null && !isAnimating(mScrimInFront)
+                && !isAnimating(mScrimBehind)) {
+            mOnAnimationFinished.run();
+            mOnAnimationFinished = null;
+        }
         return true;
     }
 
@@ -649,17 +658,6 @@
         }
     }
 
-    private void endAnimateKeyguardFadingOut(boolean force) {
-        mAnimateKeyguardFadingOut = false;
-        if (force || (!isAnimating(mScrimInFront) && !isAnimating(mScrimBehind))) {
-            if (mOnAnimationFinished != null) {
-                mOnAnimationFinished.run();
-                mOnAnimationFinished = null;
-            }
-            mKeyguardFadingOutInProgress = false;
-        }
-    }
-
     private boolean isAnimating(View scrim) {
         return scrim.getTag(TAG_KEY_ANIM) != null;
     }
@@ -693,7 +691,13 @@
     }
 
     private void updateHeadsUpScrim(boolean animate) {
-        updateScrim(animate, mHeadsUpScrim, calculateHeadsUpAlpha());
+        if (animate) {
+            mAnimationDuration = ANIMATION_DURATION;
+            cancelAnimator((ValueAnimator) mHeadsUpScrim.getTag(TAG_KEY_ANIM));
+            startScrimAnimation(mHeadsUpScrim, mHeadsUpScrim.getAlpha());
+        } else {
+            setOrAdaptCurrentAnimation(mHeadsUpScrim);
+        }
     }
 
     @VisibleForTesting
@@ -701,32 +705,28 @@
         mOnAnimationFinished = onAnimationFinished;
     }
 
-    private void updateScrim(boolean animate, View scrim, float alpha) {
-        final float currentAlpha = scrim instanceof ScrimView ? ((ScrimView) scrim).getViewAlpha()
-            : scrim.getAlpha();
+    private void updateScrim(ScrimView scrim, float alpha) {
+        final float currentAlpha = scrim.getViewAlpha();
 
         ValueAnimator previousAnimator = ViewState.getChildTag(scrim, TAG_KEY_ANIM);
-        float animEndValue = -1;
         if (previousAnimator != null) {
-            if (animate || alpha == currentAlpha) {
+            if (mAnimateChange) {
                 // We are not done yet! Defer calling the finished listener.
-                if (animate) {
-                    mDeferFinishedListener = true;
-                }
-                cancelAnimator(previousAnimator);
-                mDeferFinishedListener = false;
-            } else {
-                animEndValue = ViewState.getChildTag(scrim, TAG_END_ALPHA);
+                mDeferFinishedListener = true;
             }
+            // Previous animators should always be cancelled. Not doing so would cause
+            // overlap, especially on states that don't animate, leading to flickering,
+            // and in the worst case, an internal state that doesn't represent what
+            // transitionTo requested.
+            cancelAnimator(previousAnimator);
+            mDeferFinishedListener = false;
         }
 
         if (mPendingFrameCallback != null) {
             // Display is off and we're waiting.
-            cancelAnimator(previousAnimator);
             return;
         } else if (mBlankScreen) {
             // Need to blank the display before continuing.
-            cancelAnimator(previousAnimator);
             blankDisplay();
             return;
         } else if (!mScreenBlankingCallbackCalled) {
@@ -743,37 +743,16 @@
             mLightBarController.setScrimAlpha(alpha);
         }
 
-        final ScrimView scrimView = scrim instanceof  ScrimView ? (ScrimView) scrim : null;
-        final boolean wantsAlphaUpdate = alpha != currentAlpha && alpha != animEndValue;
-        final boolean wantsTintUpdate = scrimView != null
-                && scrimView.getTint() != getCurrentScrimTint(scrimView);
+        final boolean wantsAlphaUpdate = alpha != currentAlpha;
+        final boolean wantsTintUpdate = scrim.getTint() != getCurrentScrimTint(scrim);
 
         if (wantsAlphaUpdate || wantsTintUpdate) {
-            if (animate) {
-                final float fromAlpha = scrimView == null ? scrim.getAlpha()
-                        : scrimView.getViewAlpha();
-                startScrimAnimation(scrim, fromAlpha);
-                scrim.setTag(TAG_START_ALPHA, currentAlpha);
-                scrim.setTag(TAG_END_ALPHA, alpha);
+            if (mAnimateChange) {
+                startScrimAnimation(scrim, currentAlpha);
             } else {
-                if (previousAnimator != null) {
-                    float previousStartValue = ViewState.getChildTag(scrim, TAG_START_ALPHA);
-                    float previousEndValue = ViewState.getChildTag(scrim, TAG_END_ALPHA);
-                    // we need to increase all animation keyframes of the previous animator by the
-                    // relative change to the end value
-                    PropertyValuesHolder[] values = previousAnimator.getValues();
-                    float relativeDiff = alpha - previousEndValue;
-                    float newStartValue = previousStartValue + relativeDiff;
-                    newStartValue = Math.max(0, Math.min(1.0f, newStartValue));
-                    values[0].setFloatValues(newStartValue, alpha);
-                    scrim.setTag(TAG_START_ALPHA, newStartValue);
-                    scrim.setTag(TAG_END_ALPHA, alpha);
-                    previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
-                } else {
-                    // update the alpha directly
-                    updateScrimColor(scrim, alpha, getCurrentScrimTint(scrim));
-                    onFinished();
-                }
+                // update the alpha directly
+                updateScrimColor(scrim, alpha, getCurrentScrimTint(scrim));
+                onFinished();
             }
         } else {
             onFinished();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 408cd85..e8ac326 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -3540,7 +3540,7 @@
                 .alpha(0f)
                 .setStartDelay(0)
                 .setDuration(FADE_KEYGUARD_DURATION_PULSING)
-                .setInterpolator(ScrimController.KEYGUARD_FADE_OUT_INTERPOLATOR)
+                .setInterpolator(Interpolators.ALPHA_OUT)
                 .withEndAction(()-> {
                     hideKeyguard();
                     mStatusBarKeyguardViewManager.onKeyguardFadedAway();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index e7b802d..aec05cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -232,12 +232,7 @@
                     performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
                 }
                 mIsPressed = true;
-                if (isProxyConnected) {
-                    // Provide small vibration for quick step or immediate down feedback
-                    AsyncTask.execute(() ->
-                            mVibrator.vibrate(VibrationEffect
-                                    .get(VibrationEffect.EFFECT_TICK, false)));
-                } else {
+                if (!isProxyConnected) {
                     playSoundEffect(SoundEffectConstants.CLICK);
                     setPressed(mIsPressed);
                 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index 168d8d3..3ed2fe1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -77,7 +77,7 @@
         mLightBarController = mock(LightBarController.class);
         mScrimBehind = new ScrimView(getContext());
         mScrimInFront = new ScrimView(getContext());
-        mHeadsUpScrim = mock(View.class);
+        mHeadsUpScrim = new View(getContext());
         mWakeLock = mock(WakeLock.class);
         mAlarmManager = mock(AlarmManager.class);
         mAlwaysOnEnabled = true;
@@ -384,6 +384,56 @@
         testConservesNotificationDensity(3 /* count */, ScrimController.GRADIENT_SCRIM_ALPHA_BUSY);
     }
 
+    @Test
+    public void testHeadsUpScrimOpacity() {
+        mScrimController.setPanelExpansion(0f);
+        mScrimController.onHeadsUpPinned(null /* row */);
+        mScrimController.finishAnimationsImmediately();
+
+        Assert.assertNotEquals("Heads-up scrim should be visible", 0f,
+                mHeadsUpScrim.getAlpha(), 0.01f);
+
+        mScrimController.onHeadsUpUnPinned(null /* row */);
+        mScrimController.finishAnimationsImmediately();
+
+        Assert.assertEquals("Heads-up scrim should have disappeared", 0f,
+                mHeadsUpScrim.getAlpha(), 0.01f);
+    }
+
+    @Test
+    public void testHeadsUpScrimCounting() {
+        mScrimController.setPanelExpansion(0f);
+        mScrimController.onHeadsUpPinned(null /* row */);
+        mScrimController.onHeadsUpPinned(null /* row */);
+        mScrimController.onHeadsUpPinned(null /* row */);
+        mScrimController.finishAnimationsImmediately();
+
+        Assert.assertNotEquals("Heads-up scrim should be visible", 0f,
+                mHeadsUpScrim.getAlpha(), 0.01f);
+
+        mScrimController.onHeadsUpUnPinned(null /* row */);
+        mScrimController.finishAnimationsImmediately();
+
+        Assert.assertEquals("Heads-up scrim should only disappear when counter reaches 0", 1f,
+                mHeadsUpScrim.getAlpha(), 0.01f);
+
+        mScrimController.onHeadsUpUnPinned(null /* row */);
+        mScrimController.onHeadsUpUnPinned(null /* row */);
+        mScrimController.finishAnimationsImmediately();
+        Assert.assertEquals("Heads-up scrim should have disappeared", 0f,
+                mHeadsUpScrim.getAlpha(), 0.01f);
+    }
+
+    @Test
+    public void testNoHeadsUpScrimExpanded() {
+        mScrimController.setPanelExpansion(1f);
+        mScrimController.onHeadsUpPinned(null /* row */);
+        mScrimController.finishAnimationsImmediately();
+
+        Assert.assertEquals("Heads-up scrim should not be visible when shade is expanded", 0f,
+                mHeadsUpScrim.getAlpha(), 0.01f);
+    }
+
     /**
      * Conserves old notification density after leaving state and coming back.
      *
@@ -437,7 +487,7 @@
         private FakeHandler mHandler;
         private boolean mAnimationCancelled;
 
-        public SynchronousScrimController(LightBarController lightBarController,
+        SynchronousScrimController(LightBarController lightBarController,
                 ScrimView scrimBehind, ScrimView scrimInFront, View headsUpScrim,
                 Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
                 AlarmManager alarmManager) {
@@ -446,7 +496,7 @@
             mHandler = new FakeHandler(Looper.myLooper());
         }
 
-        public void finishAnimationsImmediately() {
+        void finishAnimationsImmediately() {
             boolean[] animationFinished = {false};
             setOnAnimationFinished(()-> animationFinished[0] = true);
 
@@ -458,19 +508,20 @@
             // Force finish all animations.
             endAnimation(mScrimBehind, TAG_KEY_ANIM);
             endAnimation(mScrimInFront, TAG_KEY_ANIM);
+            endAnimation(mHeadsUpScrim, TAG_KEY_ANIM);
 
             if (!animationFinished[0]) {
                 throw new IllegalStateException("Animation never finished");
             }
         }
 
-        public boolean wasAnimationJustCancelled() {
+        boolean wasAnimationJustCancelled() {
             final boolean wasCancelled = mAnimationCancelled;
             mAnimationCancelled = false;
             return wasCancelled;
         }
 
-        private void endAnimation(ScrimView scrimView, int tag) {
+        private void endAnimation(View scrimView, int tag) {
             Animator animator = (Animator) scrimView.getTag(tag);
             if (animator != null) {
                 animator.end();
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 7819a80..57e3c75 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -5369,6 +5369,16 @@
     // OS: P
     FIELD_DEVICE_ROTATION = 1329;
 
+    // OPEN: TV Settings > Inputs > Input Options
+    // CATEGORY: SETTINGS
+    // OS: P
+    SETTINGS_TV_INPUT_OPTIONS_CATEGORY = 1330;
+
+    // OPEN: TV Settings > Network & Internet > Add known WIFI network
+    // CATEGORY: SETTINGS
+    // OS: P
+    SETTINGS_TV_WIFI_ADD_KNOWN_CATEGORY = 1331;
+
     // ---- End P Constants, all P constants go above this line ----
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index b32be73..52d0e08e 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -24,8 +24,9 @@
 #include <utils/misc.h>
 #include <inttypes.h>
 
+#include <android-base/macros.h>
 #include <androidfw/Asset.h>
-#include <androidfw/AssetManager.h>
+#include <androidfw/AssetManager2.h>
 #include <androidfw/ResourceTypes.h>
 #include <android-base/macros.h>
 
@@ -1664,18 +1665,22 @@
 static jlong
 nFileA3DCreateFromAsset(JNIEnv *_env, jobject _this, jlong con, jobject _assetMgr, jstring _path)
 {
-    AssetManager* mgr = assetManagerForJavaObject(_env, _assetMgr);
+    Guarded<AssetManager2>* mgr = AssetManagerForJavaObject(_env, _assetMgr);
     if (mgr == nullptr) {
         return 0;
     }
 
     AutoJavaStringToUTF8 str(_env, _path);
-    Asset* asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
-    if (asset == nullptr) {
-        return 0;
+    std::unique_ptr<Asset> asset;
+    {
+        ScopedLock<AssetManager2> locked_mgr(*mgr);
+        asset = locked_mgr->Open(str.c_str(), Asset::ACCESS_BUFFER);
+        if (asset == nullptr) {
+            return 0;
+        }
     }
 
-    jlong id = (jlong)(uintptr_t)rsaFileA3DCreateFromAsset((RsContext)con, asset);
+    jlong id = (jlong)(uintptr_t)rsaFileA3DCreateFromAsset((RsContext)con, asset.release());
     return id;
 }
 
@@ -1752,22 +1757,25 @@
 nFontCreateFromAsset(JNIEnv *_env, jobject _this, jlong con, jobject _assetMgr, jstring _path,
                      jfloat fontSize, jint dpi)
 {
-    AssetManager* mgr = assetManagerForJavaObject(_env, _assetMgr);
+    Guarded<AssetManager2>* mgr = AssetManagerForJavaObject(_env, _assetMgr);
     if (mgr == nullptr) {
         return 0;
     }
 
     AutoJavaStringToUTF8 str(_env, _path);
-    Asset* asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
-    if (asset == nullptr) {
-        return 0;
+    std::unique_ptr<Asset> asset;
+    {
+        ScopedLock<AssetManager2> locked_mgr(*mgr);
+        asset = locked_mgr->Open(str.c_str(), Asset::ACCESS_BUFFER);
+        if (asset == nullptr) {
+            return 0;
+        }
     }
 
     jlong id = (jlong)(uintptr_t)rsFontCreateFromMemory((RsContext)con,
                                            str.c_str(), str.length(),
                                            fontSize, dpi,
                                            asset->getBuffer(false), asset->getLength());
-    delete asset;
     return id;
 }
 
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 05237af..a06490b 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -22,6 +22,7 @@
 import static com.android.server.autofill.Helper.bundleToString;
 import static com.android.server.autofill.Helper.sDebug;
 import static com.android.server.autofill.Helper.sPartitionMaxCount;
+import static com.android.server.autofill.Helper.sVisibleDatasetsMaxCount;
 import static com.android.server.autofill.Helper.sVerbose;
 
 import android.annotation.NonNull;
@@ -463,6 +464,24 @@
     }
 
     // Called by Shell command.
+    public int getMaxVisibleDatasets() {
+        mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
+
+        synchronized (mLock) {
+            return sVisibleDatasetsMaxCount;
+        }
+    }
+
+    // Called by Shell command.
+    public void setMaxVisibleDatasets(int max) {
+        mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
+        Slog.i(TAG, "setMaxVisibleDatasets(): " + max);
+        synchronized (mLock) {
+            sVisibleDatasetsMaxCount = max;
+        }
+    }
+
+    // Called by Shell command.
     public void getScore(@Nullable String algorithmName, @NonNull String value1,
             @NonNull String value2, @NonNull RemoteCallback callback) {
         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
@@ -1009,6 +1028,7 @@
                     pw.print("Verbose mode: "); pw.println(sVerbose);
                     pw.print("Disabled users: "); pw.println(mDisabledUsers);
                     pw.print("Max partitions per session: "); pw.println(sPartitionMaxCount);
+                    pw.print("Max visible datasets: "); pw.println(sVisibleDatasetsMaxCount);
                     pw.println("User data constraints: "); UserData.dumpConstraints(prefix, pw);
                     final int size = mServicesCache.size();
                     pw.print("Cached services: ");
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
index 4d69ef9..1904061 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
@@ -77,12 +77,18 @@
             pw.println("  get max_partitions");
             pw.println("    Gets the maximum number of partitions per session.");
             pw.println("");
+            pw.println("  get max_visible_datasets");
+            pw.println("    Gets the maximum number of visible datasets in the UI.");
+            pw.println("");
             pw.println("  set log_level [off | debug | verbose]");
             pw.println("    Sets the Autofill log level.");
             pw.println("");
             pw.println("  set max_partitions number");
             pw.println("    Sets the maximum number of partitions per session.");
             pw.println("");
+            pw.println("  set max_visible_datasets number");
+            pw.println("    Sets the maximum number of visible datasets in the UI.");
+            pw.println("");
             pw.println("  list sessions [--user USER_ID]");
             pw.println("    Lists all pending sessions.");
             pw.println("");
@@ -105,6 +111,8 @@
                 return getLogLevel(pw);
             case "max_partitions":
                 return getMaxPartitions(pw);
+            case "max_visible_datasets":
+                return getMaxVisibileDatasets(pw);
             case "fc_score":
                 return getFieldClassificationScore(pw);
             default:
@@ -121,6 +129,8 @@
                 return setLogLevel(pw);
             case "max_partitions":
                 return setMaxPartitions();
+            case "max_visible_datasets":
+                return setMaxVisibileDatasets();
             default:
                 pw.println("Invalid set: " + what);
                 return -1;
@@ -173,6 +183,16 @@
         return 0;
     }
 
+    private int getMaxVisibileDatasets(PrintWriter pw) {
+        pw.println(mService.getMaxVisibleDatasets());
+        return 0;
+    }
+
+    private int setMaxVisibileDatasets() {
+        mService.setMaxVisibleDatasets(Integer.parseInt(getNextArgRequired()));
+        return 0;
+    }
+
     private int getFieldClassificationScore(PrintWriter pw) {
         final String nextArg = getNextArgRequired();
         final String algorithm, value1;
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index 5ef467d..232dfdc 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -61,6 +61,13 @@
      */
     static int sPartitionMaxCount = 10;
 
+    /**
+     * Maximum number of visible datasets in the dataset picker UI.
+     *
+     * <p>Can be modified using {@code cmd autofill set max_visible_datasets}.
+     */
+    public static int sVisibleDatasetsMaxCount = 3;
+
     private Helper() {
         throw new UnsupportedOperationException("contains static members only");
     }
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index dbed242..a32078c 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -58,6 +58,8 @@
 import com.android.server.UiThread;
 import com.android.server.autofill.Helper;
 
+import static com.android.server.autofill.Helper.sVisibleDatasetsMaxCount;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -69,8 +71,6 @@
 final class FillUi {
     private static final String TAG = "FillUi";
 
-    private static final int VISIBLE_OPTIONS_MAX_COUNT = 3;
-
     private static final TypedValue sTempTypedValue = new TypedValue();
 
     public static final class AutofillFrameLayout extends FrameLayout {
@@ -375,7 +375,7 @@
                     }
                     requestShowFillUi();
                 }
-                if (mAdapter.getCount() > VISIBLE_OPTIONS_MAX_COUNT) {
+                if (mAdapter.getCount() > sVisibleDatasetsMaxCount) {
                     mListView.setVerticalScrollBarEnabled(true);
                     mListView.onVisibilityAggregated(true);
                 } else {
@@ -475,7 +475,7 @@
                     changed = true;
                 }
                 // Update the width to fit only the first items up to max count
-                if (i < VISIBLE_OPTIONS_MAX_COUNT) {
+                if (i < sVisibleDatasetsMaxCount) {
                     final int clampedMeasuredHeight = Math.min(view.getMeasuredHeight(), maxSize.y);
                     final int newContentHeight = mContentHeight + clampedMeasuredHeight;
                     if (newContentHeight != mContentHeight) {
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 53c9ecb..15f3a23 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -61,8 +61,8 @@
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.XmlUtils;
-
 import com.android.internal.util.function.pooled.PooledLambda;
+
 import libcore.util.EmptyArray;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -1961,10 +1961,16 @@
         int mode;
         int packageUid;
         int nonpackageUid;
+        final static Binder sBinder = new Binder();
+        IBinder mToken;
 
         Shell(IAppOpsService iface, AppOpsService internal) {
             mInterface = iface;
             mInternal = internal;
+            try {
+                mToken = mInterface.getToken(sBinder);
+            } catch (RemoteException e) {
+            }
         }
 
         @Override
@@ -2149,6 +2155,10 @@
         pw.println("AppOps service (appops) commands:");
         pw.println("  help");
         pw.println("    Print this help text.");
+        pw.println("  start [--user <USER_ID>] <PACKAGE | UID> <OP> ");
+        pw.println("    Starts a given operation for a particular application.");
+        pw.println("  stop [--user <USER_ID>] <PACKAGE | UID> <OP> ");
+        pw.println("    Stops a given operation for a particular application.");
         pw.println("  set [--user <USER_ID>] <PACKAGE | UID> <OP> <MODE>");
         pw.println("    Set the mode for a particular application and operation.");
         pw.println("  get [--user <USER_ID>] <PACKAGE | UID> [<OP>]");
@@ -2347,6 +2357,34 @@
                     }
                     return 0;
                 }
+                case "start": {
+                    int res = shell.parseUserPackageOp(true, err);
+                    if (res < 0) {
+                        return res;
+                    }
+
+                    if (shell.packageName != null) {
+                        shell.mInterface.startOperation(shell.mToken,
+                                shell.op, shell.packageUid, shell.packageName, true);
+                    } else {
+                        return -1;
+                    }
+                    return 0;
+                }
+                case "stop": {
+                    int res = shell.parseUserPackageOp(true, err);
+                    if (res < 0) {
+                        return res;
+                    }
+
+                    if (shell.packageName != null) {
+                        shell.mInterface.finishOperation(shell.mToken,
+                                shell.op, shell.packageUid, shell.packageName);
+                    } else {
+                        return -1;
+                    }
+                    return 0;
+                }
                 default:
                     return shell.handleDefaultCommands(cmd);
             }
diff --git a/services/core/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java
index 965714d..26a8cf7 100644
--- a/services/core/java/com/android/server/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/TextServicesManagerService.java
@@ -16,6 +16,9 @@
 
 package com.android.server;
 
+import static android.view.textservice.TextServicesManager.DISABLE_PER_PROFILE_SPELL_CHECKER;
+
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.inputmethod.InputMethodUtils;
 import com.android.internal.textservice.ISpellCheckerService;
@@ -24,6 +27,7 @@
 import com.android.internal.textservice.ISpellCheckerSessionListener;
 import com.android.internal.textservice.ITextServicesManager;
 import com.android.internal.textservice.ITextServicesSessionListener;
+import com.android.internal.textservice.LazyIntToIntMap;
 import com.android.internal.util.DumpUtils;
 
 import org.xmlpull.v1.XmlPullParserException;
@@ -79,6 +83,10 @@
     private final UserManager mUserManager;
     private final Object mLock = new Object();
 
+    @NonNull
+    @GuardedBy("mLock")
+    private final LazyIntToIntMap mSpellCheckerOwnerUserIdMap;
+
     private static class TextServicesData {
         @UserIdInt
         private final int mUserId;
@@ -294,6 +302,9 @@
 
     void onStopUser(@UserIdInt int userId) {
         synchronized (mLock) {
+            // Clear user ID mapping table.
+            mSpellCheckerOwnerUserIdMap.delete(userId);
+
             // Clean per-user data
             TextServicesData tsd = mUserData.get(userId);
             if (tsd == null) return;
@@ -313,12 +324,32 @@
     public TextServicesManagerService(Context context) {
         mContext = context;
         mUserManager = mContext.getSystemService(UserManager.class);
+        mSpellCheckerOwnerUserIdMap = new LazyIntToIntMap(callingUserId -> {
+            if (DISABLE_PER_PROFILE_SPELL_CHECKER) {
+                final long token = Binder.clearCallingIdentity();
+                try {
+                    final UserInfo parent = mUserManager.getProfileParent(callingUserId);
+                    return (parent != null) ? parent.id : callingUserId;
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
+            } else {
+                return callingUserId;
+            }
+        });
 
         mMonitor = new TextServicesMonitor();
         mMonitor.register(context, null, UserHandle.ALL, true);
     }
 
     private void initializeInternalStateLocked(@UserIdInt int userId) {
+        // When DISABLE_PER_PROFILE_SPELL_CHECKER is true, we make sure here that work profile users
+        // will never have non-null TextServicesData for their user ID.
+        if (DISABLE_PER_PROFILE_SPELL_CHECKER
+                && userId != mSpellCheckerOwnerUserIdMap.get(userId)) {
+            return;
+        }
+
         TextServicesData tsd = mUserData.get(userId);
         if (tsd == null) {
             tsd = new TextServicesData(userId, mContext);
@@ -470,7 +501,7 @@
     public SpellCheckerInfo getCurrentSpellChecker(String locale) {
         int userId = UserHandle.getCallingUserId();
         synchronized (mLock) {
-            TextServicesData tsd = mUserData.get(userId);
+            final TextServicesData tsd = getDataFromCallingUserIdLocked(userId);
             if (tsd == null) return null;
 
             return tsd.getCurrentSpellChecker();
@@ -488,7 +519,7 @@
         final int userId = UserHandle.getCallingUserId();
 
         synchronized (mLock) {
-            TextServicesData tsd = mUserData.get(userId);
+            final TextServicesData tsd = getDataFromCallingUserIdLocked(userId);
             if (tsd == null) return null;
 
             subtypeHashCode =
@@ -569,7 +600,7 @@
         int callingUserId = UserHandle.getCallingUserId();
 
         synchronized (mLock) {
-            TextServicesData tsd = mUserData.get(callingUserId);
+            final TextServicesData tsd = getDataFromCallingUserIdLocked(callingUserId);
             if (tsd == null) return;
 
             HashMap<String, SpellCheckerInfo> spellCheckerMap = tsd.mSpellCheckerMap;
@@ -606,7 +637,7 @@
         int userId = UserHandle.getCallingUserId();
 
         synchronized (mLock) {
-            TextServicesData tsd = mUserData.get(userId);
+            final TextServicesData tsd = getDataFromCallingUserIdLocked(userId);
             if (tsd == null) return false;
 
             return tsd.isSpellCheckerEnabled();
@@ -643,7 +674,7 @@
         int callingUserId = UserHandle.getCallingUserId();
 
         synchronized (mLock) {
-            TextServicesData tsd = mUserData.get(callingUserId);
+            final TextServicesData tsd = getDataFromCallingUserIdLocked(callingUserId);
             if (tsd == null) return null;
 
             ArrayList<SpellCheckerInfo> spellCheckerList = tsd.mSpellCheckerList;
@@ -666,7 +697,7 @@
         int userId = UserHandle.getCallingUserId();
 
         synchronized (mLock) {
-            TextServicesData tsd = mUserData.get(userId);
+            final TextServicesData tsd = getDataFromCallingUserIdLocked(userId);
             if (tsd == null) return;
 
             final ArrayList<SpellCheckerBindGroup> removeList = new ArrayList<>();
@@ -737,6 +768,36 @@
         }
     }
 
+    /**
+     * @param callingUserId user ID of the calling process
+     * @return {@link TextServicesData} for the given user.  {@code null} if spell checker is not
+     *         temporarily / permanently available for the specified user
+     */
+    @Nullable
+    private TextServicesData getDataFromCallingUserIdLocked(@UserIdInt int callingUserId) {
+        final int spellCheckerOwnerUserId = mSpellCheckerOwnerUserIdMap.get(callingUserId);
+        final TextServicesData data = mUserData.get(spellCheckerOwnerUserId);
+        if (DISABLE_PER_PROFILE_SPELL_CHECKER) {
+            if (spellCheckerOwnerUserId != callingUserId) {
+                // Calling process is running under child profile.
+                if (data == null) {
+                    return null;
+                }
+                final SpellCheckerInfo info = data.getCurrentSpellChecker();
+                if (info == null) {
+                    return null;
+                }
+                final ServiceInfo serviceInfo = info.getServiceInfo();
+                if ((serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+                    // To be conservative, non pre-installed spell checker services are not allowed
+                    // to be used for child profiles.
+                    return null;
+                }
+            }
+        }
+        return data;
+    }
+
     private static final class SessionRequest {
         public final int mUid;
         @Nullable
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0de4f86..7656453 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -192,7 +192,8 @@
 import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
 import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
 import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
-import static com.android.server.am.MemoryStatUtil.readMemoryStatFromMemcg;
+import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
+import static com.android.server.am.MemoryStatUtil.hasMemcg;
 import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
 import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
 import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
@@ -685,7 +686,7 @@
 
     private final ActivityStartController mActivityStartController;
 
-    final ClientLifecycleManager mLifecycleManager;
+    private final ClientLifecycleManager mLifecycleManager;
 
     final TaskChangeNotificationController mTaskChangeNotificationController;
 
@@ -5925,6 +5926,12 @@
             Slog.d(TAG_PROCESSES, "Received spurious death notification for thread "
                     + thread.asBinder());
         }
+
+        // On the device which doesn't have Cgroup, log LmkStateChanged which is used as a signal
+        // for pulling memory stats of other running processes when this process died.
+        if (!hasMemcg()) {
+            StatsLog.write(StatsLog.APP_DIED, SystemClock.elapsedRealtime());
+        }
     }
 
     /**
@@ -12303,6 +12310,10 @@
         return mActivityStartController;
     }
 
+    ClientLifecycleManager getLifecycleManager() {
+        return mLifecycleManager;
+    }
+
     PackageManagerInternal getPackageManagerInternalLocked() {
         if (mPackageManagerInt == null) {
             mPackageManagerInt = LocalServices.getService(PackageManagerInternal.class);
@@ -26155,7 +26166,7 @@
                     final ProcessRecord r = mPidsSelfLocked.valueAt(i);
                     final int pid = r.pid;
                     final int uid = r.uid;
-                    final MemoryStat memoryStat = readMemoryStatFromMemcg(uid, pid);
+                    final MemoryStat memoryStat = readMemoryStatFromFilesystem(uid, pid);
                     if (memoryStat == null) {
                         continue;
                     }
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index 5d5ed55..352b757 100644
--- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
@@ -34,7 +34,7 @@
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.am.MemoryStatUtil.MemoryStat;
-import static com.android.server.am.MemoryStatUtil.readMemoryStatFromMemcg;
+import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
 
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -635,7 +635,7 @@
 
         final int pid = info.processRecord.pid;
         final int uid = info.applicationInfo.uid;
-        final MemoryStat memoryStat = readMemoryStatFromMemcg(uid, pid);
+        final MemoryStat memoryStat = readMemoryStatFromFilesystem(uid, pid);
         if (memoryStat == null) {
             if (DEBUG_METRICS) Slog.i(TAG, "logAppStartMemoryStateCapture memoryStat null");
             return;
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 519024a..e6d6fdf 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -665,7 +665,7 @@
                     "Reporting activity moved to display" + ", activityRecord=" + this
                             + ", displayId=" + displayId + ", config=" + config);
 
-            service.mLifecycleManager.scheduleTransaction(app.thread, appToken,
+            service.getLifecycleManager().scheduleTransaction(app.thread, appToken,
                     MoveToDisplayItem.obtain(displayId, config));
         } catch (RemoteException e) {
             // If process died, whatever.
@@ -683,7 +683,7 @@
             if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + this + ", config: "
                     + config);
 
-            service.mLifecycleManager.scheduleTransaction(app.thread, appToken,
+            service.getLifecycleManager().scheduleTransaction(app.thread, appToken,
                     ActivityConfigurationChangeItem.obtain(config));
         } catch (RemoteException e) {
             // If process died, whatever.
@@ -710,7 +710,7 @@
 
     private void scheduleMultiWindowModeChanged(Configuration overrideConfig) {
         try {
-            service.mLifecycleManager.scheduleTransaction(app.thread, appToken,
+            service.getLifecycleManager().scheduleTransaction(app.thread, appToken,
                     MultiWindowModeChangeItem.obtain(mLastReportedMultiWindowMode,
                             overrideConfig));
         } catch (Exception e) {
@@ -738,7 +738,7 @@
 
     private void schedulePictureInPictureModeChanged(Configuration overrideConfig) {
         try {
-            service.mLifecycleManager.scheduleTransaction(app.thread, appToken,
+            service.getLifecycleManager().scheduleTransaction(app.thread, appToken,
                     PipModeChangeItem.obtain(mLastReportedPictureInPictureMode,
                             overrideConfig));
         } catch (Exception e) {
@@ -1428,7 +1428,7 @@
             try {
                 ArrayList<ReferrerIntent> ar = new ArrayList<>(1);
                 ar.add(rintent);
-                service.mLifecycleManager.scheduleTransaction(app.thread, appToken,
+                service.getLifecycleManager().scheduleTransaction(app.thread, appToken,
                         NewIntentItem.obtain(ar, mState == PAUSED));
                 unsent = false;
             } catch (RemoteException e) {
@@ -1615,20 +1615,30 @@
         if (DEBUG_STATES) Slog.v(TAG_STATES, "State movement: " + this + " from:" + getState()
                         + " to:" + state + " reason:" + reason);
 
+        if (state == mState) {
+            // No need to do anything if state doesn't change.
+            if (DEBUG_STATES) Slog.v(TAG_STATES, "State unchanged from:" + state);
+            return;
+        }
+
+        if (isState(DESTROYED) || (state != DESTROYED && isState(DESTROYING))) {
+            // We cannot move backwards from destroyed and destroying states.
+            throw new IllegalArgumentException("cannot move back states once destroying"
+                    + "current:" + mState + " requested:" + state);
+        }
+
         final ActivityState prev = mState;
-        final boolean stateChanged = prev != state;
+        mState = state;
+
+        if (mRecentTransitions.size() == MAX_STORED_STATE_TRANSITIONS) {
+            mRecentTransitions.remove(0);
+        }
+
+        mRecentTransitions.add(new StateTransition(prev, state, reason));
 
         mState = state;
 
-        if (stateChanged) {
-            if (mRecentTransitions.size() == MAX_STORED_STATE_TRANSITIONS) {
-                mRecentTransitions.remove(0);
-            }
-
-            mRecentTransitions.add(new StateTransition(prev, state, reason));
-        }
-
-        if (stateChanged && isState(DESTROYING, DESTROYED)) {
+        if (isState(DESTROYING, DESTROYED)) {
             makeFinishingLocked();
 
             // When moving to the destroyed state, immediately destroy the activity in the
@@ -1726,28 +1736,32 @@
             setVisible(true);
             sleeping = false;
             app.pendingUiClean = true;
-            service.mLifecycleManager.scheduleTransaction(app.thread, appToken,
+            service.getLifecycleManager().scheduleTransaction(app.thread, appToken,
                     WindowVisibilityItem.obtain(true /* showWindow */));
             // The activity may be waiting for stop, but that is no longer appropriate for it.
             mStackSupervisor.mStoppingActivities.remove(this);
             mStackSupervisor.mGoingToSleepActivities.remove(this);
 
-            // If the activity is stopped or stopping, cycle to the paused state.
-            if (isState(STOPPED, STOPPING)) {
+            // If the activity is stopped or stopping, cycle to the paused state. We avoid doing
+            // this when there is an activity waiting to become translucent as the extra binder
+            // calls will lead to noticeable jank. A later call to
+            // ActivityStack#ensureActivitiesVisibleLocked will bring the activity to the proper
+            // paused state.
+            if (isState(STOPPED, STOPPING) && stack.mTranslucentActivityWaiting == null) {
                 // Capture reason before state change
                 final String reason = getLifecycleDescription("makeVisibleIfNeeded");
 
                 // An activity must be in the {@link PAUSING} state for the system to validate
                 // the move to {@link PAUSED}.
                 setState(PAUSING, "makeVisibleIfNeeded");
-                service.mLifecycleManager.scheduleTransaction(app.thread, appToken,
+                service.getLifecycleManager().scheduleTransaction(app.thread, appToken,
                         PauseActivityItem.obtain(finishing, false /* userLeaving */,
                                 configChangeFlags, false /* dontReport */)
                                 .setDescription(reason));
             }
         } catch (Exception e) {
             // Just skip on any failure; we'll make it visible when it next restarts.
-            Slog.w(TAG, "Exception thrown making visibile: " + intent.getComponent(), e);
+            Slog.w(TAG, "Exception thrown making visible: " + intent.getComponent(), e);
         }
         handleAlreadyVisible();
     }
@@ -2708,7 +2722,7 @@
             final ClientTransaction transaction = ClientTransaction.obtain(app.thread, appToken);
             transaction.addCallback(callbackItem);
             transaction.setLifecycleStateRequest(lifecycleItem);
-            service.mLifecycleManager.scheduleTransaction(transaction);
+            service.getLifecycleManager().scheduleTransaction(transaction);
             // Note: don't need to call pauseIfSleepingLocked() here, because the caller will only
             // request resume if this activity is currently resumed, which implies we aren't
             // sleeping.
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 9276abe..f4a4af2 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1472,7 +1472,7 @@
                         prev.shortComponentName, "userLeaving=" + userLeaving);
                 mService.updateUsageStats(prev, false);
 
-                mService.mLifecycleManager.scheduleTransaction(prev.app.thread, prev.appToken,
+                mService.getLifecycleManager().scheduleTransaction(prev.app.thread, prev.appToken,
                         PauseActivityItem.obtain(prev.finishing, userLeaving,
                                 prev.configChangeFlags, pauseImmediately).setDescription(
                                         prev.getLifecycleDescription("startPausingLocked")));
@@ -2109,7 +2109,7 @@
                     if (r.app != null && r.app.thread != null) {
                         if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
                                 "Scheduling invisibility: " + r);
-                        mService.mLifecycleManager.scheduleTransaction(r.app.thread, r.appToken,
+                        mService.getLifecycleManager().scheduleTransaction(r.app.thread, r.appToken,
                                 WindowVisibilityItem.obtain(false /* showWindow */));
                     }
 
@@ -2661,13 +2661,12 @@
                     next.app.pendingUiClean = true;
                     next.app.forceProcessStateUpTo(mService.mTopProcessState);
                     next.clearOptionsLocked();
-
                     transaction.setLifecycleStateRequest(
                             ResumeActivityItem.obtain(next.app.repProcState,
                                     mService.isNextTransitionForward())
                                     .setDescription(next.getLifecycleDescription(
                                             "resumeTopActivityInnerLocked")));
-                    mService.mLifecycleManager.scheduleTransaction(transaction);
+                    mService.getLifecycleManager().scheduleTransaction(transaction);
 
                     if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed "
                             + next);
@@ -3317,7 +3316,7 @@
                 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
                 list.add(new ResultInfo(resultWho, requestCode,
                         resultCode, data));
-                mService.mLifecycleManager.scheduleTransaction(r.app.thread, r.appToken,
+                mService.getLifecycleManager().scheduleTransaction(r.app.thread, r.appToken,
                         ActivityResultItem.obtain(list));
                 return;
             } catch (Exception e) {
@@ -3446,7 +3445,7 @@
                 }
                 EventLogTags.writeAmStopActivity(
                         r.userId, System.identityHashCode(r), r.shortComponentName);
-                mService.mLifecycleManager.scheduleTransaction(r.app.thread, r.appToken,
+                mService.getLifecycleManager().scheduleTransaction(r.app.thread, r.appToken,
                         StopActivityItem.obtain(r.visible, r.configChangeFlags)
                                 .setDescription(r.getLifecycleDescription("stopActivityLocked")));
                 if (shouldSleepOrShutDownActivities()) {
@@ -3782,6 +3781,15 @@
         }
         final ActivityState prevState = r.getState();
         if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to FINISHING: " + r);
+
+        // We are already destroying / have already destroyed the activity. Do not continue to
+        // modify it. Note that we do not use ActivityRecord#finishing here as finishing is not
+        // indicative of destruction (though destruction is indicative of finishing) as finishing
+        // can be delayed below.
+        if (r.isState(DESTROYING, DESTROYED)) {
+            return null;
+        }
+
         r.setState(FINISHING, "finishCurrentActivityLocked");
         final boolean finishingActivityInNonFocusedStack
                 = r.getStack() != mStackSupervisor.getFocusedStack()
@@ -4232,6 +4240,13 @@
         if (DEBUG_SWITCH || DEBUG_CLEANUP) Slog.v(TAG_SWITCH,
                 "Removing activity from " + reason + ": token=" + r
                         + ", app=" + (r.app != null ? r.app.processName : "(null)"));
+
+        if (r.isState(DESTROYING, DESTROYED)) {
+            if (DEBUG_STATES) Slog.v(TAG_STATES, "activity " + r + " already finishing."
+                    + "skipping request with reason:" + reason);
+            return false;
+        }
+
         EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
                 r.userId, System.identityHashCode(r),
                 r.getTask().taskId, r.shortComponentName, reason);
@@ -4265,7 +4280,7 @@
 
             try {
                 if (DEBUG_SWITCH) Slog.i(TAG_SWITCH, "Destroying: " + r);
-                mService.mLifecycleManager.scheduleTransaction(r.app.thread, r.appToken,
+                mService.getLifecycleManager().scheduleTransaction(r.app.thread, r.appToken,
                         DestroyActivityItem.obtain(r.finishing, r.configChangeFlags)
                             .setDescription(
                                     r.getLifecycleDescription("destroyActivityLocked:" + reason)));
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 26ffe95..740a312 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1459,7 +1459,7 @@
                 clientTransaction.setLifecycleStateRequest(lifecycleItem);
 
                 // Schedule transaction.
-                mService.mLifecycleManager.scheduleTransaction(clientTransaction);
+                mService.getLifecycleManager().scheduleTransaction(clientTransaction);
 
 
                 if ((app.info.privateFlags & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
diff --git a/services/core/java/com/android/server/am/MemoryStatUtil.java b/services/core/java/com/android/server/am/MemoryStatUtil.java
index a2a84ec..da36bd1 100644
--- a/services/core/java/com/android/server/am/MemoryStatUtil.java
+++ b/services/core/java/com/android/server/am/MemoryStatUtil.java
@@ -38,8 +38,12 @@
 final class MemoryStatUtil {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "MemoryStatUtil" : TAG_AM;
 
+    /** Path to check if device has memcg */
+    private static final String MEMCG_TEST_PATH = "/dev/memcg/apps/memory.stat";
     /** Path to memory stat file for logging app start memory state */
     private static final String MEMORY_STAT_FILE_FMT = "/dev/memcg/apps/uid_%d/pid_%d/memory.stat";
+    /** Path to procfs stat file for logging app start memory state */
+    private static final String PROC_STAT_FILE_FMT = "/proc/%d/stat";
 
     private static final Pattern PGFAULT = Pattern.compile("total_pgfault (\\d+)");
     private static final Pattern PGMAJFAULT = Pattern.compile("total_pgmajfault (\\d+)");
@@ -47,24 +51,57 @@
     private static final Pattern CACHE_IN_BYTES = Pattern.compile("total_cache (\\d+)");
     private static final Pattern SWAP_IN_BYTES = Pattern.compile("total_swap (\\d+)");
 
+    private static final int PGFAULT_INDEX = 9;
+    private static final int PGMAJFAULT_INDEX = 11;
+    private static final int RSS_IN_BYTES_INDEX = 23;
+
+    /** True if device has memcg */
+    private static volatile Boolean sDeviceHasMemCg;
+
     private MemoryStatUtil() {}
 
     /**
+     * Reads memory stat for a process.
+     *
+     * Reads from memcg if available on device, else fallback to procfs.
+     * Returns null if no stats can be read.
+     */
+    @Nullable
+    static MemoryStat readMemoryStatFromFilesystem(int uid, int pid) {
+        return hasMemcg() ? readMemoryStatFromMemcg(uid, pid) : readMemoryStatFromProcfs(pid);
+    }
+
+    /**
      * Reads memory.stat of a process from memcg.
+     *
+     * Returns null if file is not found in memcg or if file has unrecognized contents.
      */
     @Nullable
     static MemoryStat readMemoryStatFromMemcg(int uid, int pid) {
-        final String memoryStatPath = String.format(Locale.US, MEMORY_STAT_FILE_FMT, uid, pid);
-        final File memoryStatFile = new File(memoryStatPath);
-        if (!memoryStatFile.exists()) {
-            if (DEBUG_METRICS) Slog.i(TAG, memoryStatPath + " not found");
+        final String path = String.format(Locale.US, MEMORY_STAT_FILE_FMT, uid, pid);
+        return parseMemoryStatFromMemcg(readFileContents(path));
+    }
+
+    /**
+     * Reads memory stat of a process from procfs.
+     *
+     * Returns null if file is not found in procfs or if file has unrecognized contents.
+     */
+    @Nullable
+    static MemoryStat readMemoryStatFromProcfs(int pid) {
+        final String path = String.format(Locale.US, PROC_STAT_FILE_FMT, pid);
+        return parseMemoryStatFromProcfs(readFileContents(path));
+    }
+
+    private static String readFileContents(String path) {
+        final File file = new File(path);
+        if (!file.exists()) {
+            if (DEBUG_METRICS) Slog.i(TAG, path + " not found");
             return null;
         }
 
         try {
-            final String memoryStatContents = FileUtils.readTextFile(
-                    memoryStatFile, 0 /* max */, null /* ellipsis */);
-            return parseMemoryStat(memoryStatContents);
+            return FileUtils.readTextFile(file, 0 /* max */, null /* ellipsis */);
         } catch (IOException e) {
             Slog.e(TAG, "Failed to read file:", e);
             return null;
@@ -76,12 +113,12 @@
      */
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     @Nullable
-    static MemoryStat parseMemoryStat(String memoryStatContents) {
-        MemoryStat memoryStat = new MemoryStat();
-        if (memoryStatContents == null) {
-            return memoryStat;
+    static MemoryStat parseMemoryStatFromMemcg(String memoryStatContents) {
+        if (memoryStatContents == null || memoryStatContents.isEmpty()) {
+            return null;
         }
 
+        final MemoryStat memoryStat = new MemoryStat();
         Matcher m;
         m = PGFAULT.matcher(memoryStatContents);
         memoryStat.pgfault = m.find() ? Long.valueOf(m.group(1)) : 0;
@@ -96,6 +133,40 @@
         return memoryStat;
     }
 
+    /**
+     * Parses relevant statistics out from the contents of a /proc/pid/stat file in procfs.
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    @Nullable
+    static MemoryStat parseMemoryStatFromProcfs(String procStatContents) {
+        if (procStatContents == null || procStatContents.isEmpty()) {
+            return null;
+        }
+
+        final String[] splits = procStatContents.split(" ");
+        if (splits.length < 24) {
+            return null;
+        }
+
+        final MemoryStat memoryStat = new MemoryStat();
+        memoryStat.pgfault = Long.valueOf(splits[PGFAULT_INDEX]);
+        memoryStat.pgmajfault = Long.valueOf(splits[PGMAJFAULT_INDEX]);
+        memoryStat.rssInBytes = Long.valueOf(splits[RSS_IN_BYTES_INDEX]);
+        return memoryStat;
+    }
+
+    /**
+     * Checks if memcg is available on device.
+     *
+     * Touches the filesystem to do the check.
+     */
+    static boolean hasMemcg() {
+        if (sDeviceHasMemCg == null) {
+            sDeviceHasMemCg = (new File(MEMCG_TEST_PATH)).exists();
+        }
+        return sDeviceHasMemCg;
+    }
+
     static final class MemoryStat {
         /** Number of page faults */
         long pgfault;
@@ -108,4 +179,4 @@
         /** Number of bytes of swap usage */
         long swapInBytes;
     }
-}
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 3da3551..c3259c3 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -941,9 +941,7 @@
 
                         @Override
                         public void sendResult(Bundle data) throws RemoteException {
-                            if (mWakeLock.isHeld()) {
-                                mWakeLock.release();
-                            }
+                            releaseWakelock();
                         }
                     });
                 } catch (DeadObjectException e) {
@@ -951,6 +949,7 @@
                     mHandler.post(mRemoveCallbackRunnable);
                 } catch (RemoteException e) {
                     Slog.w(TAG, "Failed to invoke onLockoutReset: ", e);
+                    releaseWakelock();
                 }
             }
         }
@@ -958,9 +957,7 @@
         private final Runnable mRemoveCallbackRunnable = new Runnable() {
             @Override
             public void run() {
-                if (mWakeLock.isHeld()) {
-                    mWakeLock.release();
-                }
+                releaseWakelock();
                 removeLockoutResetCallback(FingerprintServiceLockoutResetMonitor.this);
             }
         };
@@ -970,6 +967,12 @@
             Slog.e(TAG, "Lockout reset callback binder died");
             mHandler.post(mRemoveCallbackRunnable);
         }
+
+        private void releaseWakelock() {
+            if (mWakeLock.isHeld()) {
+                mWakeLock.release();
+            }
+        }
     }
 
     private IBiometricsFingerprintClientCallback mDaemonCallback =
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 84c889c..6411ae1 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -136,8 +136,8 @@
     private IRemoteVolumeController mRvc;
 
     // MediaSession2 support
-    // TODO(jaewan): Support multi-user and managed profile.
-    // TODO(jaewan): Make it priority list for handling volume/media key.
+    // TODO(jaewan): Support multi-user and managed profile. (b/73597722)
+    // TODO(jaewan): Make it priority list for handling volume/media key. (b/73760382)
     private final Map<SessionToken2, MediaController2> mSessionRecords = new ArrayMap<>();
 
     private final List<SessionTokensListenerRecord> mSessionTokensListeners = new ArrayList<>();
@@ -184,7 +184,7 @@
         updateUser();
 
         registerPackageBroadcastReceivers();
-        // TODO(jaewan): Query per users
+        // TODO(jaewan): Query per users (b/73597722)
         buildMediaSessionService2List();
     }
 
@@ -443,6 +443,7 @@
         // TODO(jaewan): Only consider changed packages when building session service list
         //               when we make this multi-user aware. At that time,
         //               use PackageMonitor.getChangingUserId() to know which user has changed.
+        //               (b/73597722)
         IntentFilter filter = new IntentFilter();
         filter.addDataScheme("package");
         filter.addAction(Intent.ACTION_PACKAGE_ADDED);
@@ -465,7 +466,7 @@
                 }
                 // Check if the package is replacing (i.e. reinstalling)
                 final boolean isReplacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
-                // TODO(jaewan): Add multi-user support with this.
+                // TODO(jaewan): Add multi-user support with this. (b/73597722)
                 // final int uid = intent.getIntExtra(Intent.EXTRA_UID, 0);
 
                 if (DEBUG) {
@@ -506,8 +507,7 @@
         if (DEBUG) {
             Log.d(TAG, "buildMediaSessionService2List");
         }
-        // TODO(jaewan): Also query for managed profile users.
-        // TODO(jaewan): Similar codes are also at the updatable. Can't we share codes?
+        // TODO(jaewan): Also query for managed profile users. (b/73597722)
         PackageManager manager = getContext().getPackageManager();
         List<ResolveInfo> services = new ArrayList<>();
         // If multiple actions are declared for a service, browser gets higher priority.
@@ -539,7 +539,7 @@
                 ServiceInfo serviceInfo = services.get(i).serviceInfo;
                 int uid;
                 try {
-                    // TODO(jaewan): Do this per user.
+                    // TODO(jaewan): Do this per user. (b/73597722)
                     uid = manager.getPackageUid(serviceInfo.packageName,
                             PackageManager.GET_META_DATA);
                 } catch (NameNotFoundException e) {
@@ -1490,16 +1490,6 @@
                     mUserRecords.valueAt(i).dumpLocked(pw, "");
                 }
                 mAudioPlayerStateMonitor.dump(getContext(), pw, "");
-
-                // TODO(jaewan): Remove this debug command before ship.
-                if (args != null && args.length > 0 && "--purge".equals(args[0])) {
-                    mSessionRecords.clear();
-                }
-                pw.println();
-                pw.println("Session2: size=" + mSessionRecords.size());
-                for (SessionToken2 token : mSessionRecords.keySet()) {
-                    pw.println("  " + token);
-                }
             }
         }
 
@@ -1567,7 +1557,7 @@
             destroySession2Internal(token);
         }
 
-        // TODO(jaewan): Protect this API with permission
+        // TODO(jaewan): Protect this API with permission (b/73226436)
         @Override
         public List<Bundle> getSessionTokens(boolean activeSessionOnly,
                 boolean sessionServiceOnly) throws RemoteException {
@@ -1587,8 +1577,8 @@
             return tokens;
         }
 
-        // TODO(jaewan): Protect this API with permission
-        // TODO(jaewan): "userId != calling user" needs extra protection
+        // TODO(jaewan): Protect this API with permission (b/73226436)
+        // TODO(jaewan): "userId != calling user" needs extra protection (b/73226436)
         @Override
         public void addSessionTokensListener(ISessionTokensListener listener, int userId,
                 String packageName) {
@@ -1603,7 +1593,7 @@
             }
         }
 
-        // TODO(jaewan): Protect this API with permission
+        // TODO(jaewan): Protect this API with permission (b/73226436)
         @Override
         public void removeSessionTokensListener(ISessionTokensListener listener) {
             synchronized (mLock) {
@@ -2028,7 +2018,7 @@
         }
 
         @Override
-        public void onDisconnected() {
+        public void onDisconnected(MediaController2 controller) {
             destroySession2Internal(mToken);
         }
     };
@@ -2039,7 +2029,8 @@
 
         public SessionTokensListenerRecord(ISessionTokensListener listener, int userId) {
             mListener = listener;
-            mUserId = userId; // TODO should userId be mapped through mFullUserIds?
+            // TODO should userId be mapped through mFullUserIds? (b/73597722)
+            mUserId = userId;
         }
 
         @Override
@@ -2060,6 +2051,7 @@
             for (SessionToken2 token : mSessionRecords.keySet()) {
                 // TODO(jaewan): Remove the check for UserHandle.USER_ALL (shouldn't happen).
                 //               This happens when called form buildMediaSessionService2List(...).
+                //               (b/73760382)
                 if (UserHandle.getUserId(token.getUid()) == userId
                         || UserHandle.USER_ALL == userId) {
                     tokens.add(token.toBundle());
@@ -2067,7 +2059,7 @@
             }
 
             for (SessionTokensListenerRecord record : mSessionTokensListeners) {
-                // TODO should userId be mapped through mFullUserIds?
+                // TODO(jaewan): Should userId be mapped through mFullUserIds? (b/73760382)
                 if (record.mUserId == userId || record.mUserId == UserHandle.USER_ALL) {
                     try {
                         record.mListener.onSessionTokensChanged(tokens);
diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java
index 0b9412b..863045c 100644
--- a/services/core/java/com/android/server/om/OverlayManagerSettings.java
+++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java
@@ -180,12 +180,14 @@
     List<OverlayInfo> getOverlaysForTarget(@NonNull final String targetPackageName,
             final int userId) {
         return selectWhereTarget(targetPackageName, userId)
+                .filter((i) -> !i.isStatic())
                 .map(SettingsItem::getOverlayInfo)
                 .collect(Collectors.toList());
     }
 
     ArrayMap<String, List<OverlayInfo>> getOverlaysForUser(final int userId) {
         return selectWhereUser(userId)
+                .filter((i) -> !i.isStatic())
                 .map(SettingsItem::getOverlayInfo)
                 .collect(Collectors.groupingBy(info -> info.targetPackageName, ArrayMap::new,
                         Collectors.toList()));
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 98fb18a..6513683 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2981,6 +2981,9 @@
                         }
                     }
                 }
+                // Adjust seInfo to ensure apps which share a sharedUserId are placed in the same
+                // SELinux domain.
+                setting.fixSeInfoLocked();
             }
 
             // Now that we know all the packages we are keeping,
@@ -6853,6 +6856,10 @@
                     resolveInfos.remove(i);
                     continue;
                 }
+                if (blockInstant && isInstantApp(info.activityInfo.packageName, userId)) {
+                    resolveInfos.remove(i);
+                    continue;
+                }
                 // requested activity is defined in a split that hasn't been installed yet.
                 // add the installer to the resolve list
                 if (DEBUG_INSTALL) {
@@ -6867,8 +6874,6 @@
                         info.activityInfo.packageName,
                         info.activityInfo.applicationInfo.versionCode,
                         info.activityInfo.splitName);
-                installerInfo.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART
-                        | IntentFilter.MATCH_ADJUSTMENT_NORMAL;
                 // add a non-generic filter
                 installerInfo.filter = new IntentFilter();
 
@@ -6878,11 +6883,6 @@
                 installerInfo.resolvePackageName = info.getComponentInfo().packageName;
                 installerInfo.labelRes = info.resolveLabelResId();
                 installerInfo.icon = info.resolveIconResId();
-
-                // propagate priority/preferred order/default
-                installerInfo.priority = info.priority;
-                installerInfo.preferredOrder = info.preferredOrder;
-                installerInfo.isDefault = info.isDefault;
                 installerInfo.isInstantAppAvailable = true;
                 resolveInfos.set(i, installerInfo);
                 continue;
@@ -7620,10 +7620,6 @@
                             info.serviceInfo.packageName,
                             info.serviceInfo.applicationInfo.versionCode,
                             info.serviceInfo.splitName);
-                    // make sure this resolver is the default
-                    installerInfo.isDefault = true;
-                    installerInfo.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART
-                            | IntentFilter.MATCH_ADJUSTMENT_NORMAL;
                     // add a non-generic filter
                     installerInfo.filter = new IntentFilter();
                     // load resources from the correct package
@@ -7742,10 +7738,6 @@
                             info.providerInfo.packageName,
                             info.providerInfo.applicationInfo.versionCode,
                             info.providerInfo.splitName);
-                    // make sure this resolver is the default
-                    installerInfo.isDefault = true;
-                    installerInfo.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART
-                            | IntentFilter.MATCH_ADJUSTMENT_NORMAL;
                     // add a non-generic filter
                     installerInfo.filter = new IntentFilter();
                     // load resources from the correct package
@@ -10381,20 +10373,24 @@
             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
         }
 
-        // SELinux sandboxes become more restrictive as targetSdkVersion increases.
-        // To ensure that apps with sharedUserId are placed in the same selinux domain
-        // without breaking any assumptions about access, put them into the least
-        // restrictive targetSdkVersion=25 domain.
-        // TODO(b/72290969): Base this on the actual targetSdkVersion(s) of the apps within the
-        // sharedUserSetting, instead of defaulting to the least restrictive domain.
-        final int targetSdk = (sharedUserSetting != null) ? 25
-                : pkg.applicationInfo.targetSdkVersion;
+        // Apps which share a sharedUserId must be placed in the same selinux domain. If this
+        // package is the first app installed as this shared user, set seInfoTargetSdkVersion to its
+        // targetSdkVersion. These are later adjusted in PackageManagerService's constructor to be
+        // the lowest targetSdkVersion of all apps within the shared user, which corresponds to the
+        // least restrictive selinux domain.
+        // NOTE: As new packages are installed / updated, the shared user's seinfoTargetSdkVersion
+        // will NOT be modified until next boot, even if a lower targetSdkVersion is used. This
+        // ensures that all packages continue to run in the same selinux domain.
+        final int targetSdkVersion =
+            ((sharedUserSetting != null) && (sharedUserSetting.packages.size() != 0)) ?
+            sharedUserSetting.seInfoTargetSdkVersion : pkg.applicationInfo.targetSdkVersion;
         // TODO(b/71593002): isPrivileged for sharedUser and appInfo should never be out of sync.
         // They currently can be if the sharedUser apps are signed with the platform key.
         final boolean isPrivileged = (sharedUserSetting != null) ?
             sharedUserSetting.isPrivileged() | pkg.isPrivileged() : pkg.isPrivileged();
 
-        SELinuxMMAC.assignSeInfoValue(pkg, isPrivileged, targetSdk);
+        pkg.applicationInfo.seInfo = SELinuxMMAC.getSeInfo(pkg, isPrivileged,
+                pkg.applicationInfo.targetSandboxVersion, targetSdkVersion);
 
         pkg.mExtras = pkgSetting;
         pkg.applicationInfo.processName = fixProcessName(
diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java
index a9f1528..b47d966 100644
--- a/services/core/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java
@@ -64,6 +64,8 @@
     /** Required MAC permissions files */
     private static List<File> sMacPermissions = new ArrayList<>();
 
+    private static final String DEFAULT_SEINFO = "default";
+
     // Append privapp to existing seinfo label
     private static final String PRIVILEGED_APP_STR = ":privapp";
 
@@ -307,45 +309,56 @@
     }
 
     /**
-     * Applies a security label to a package based on an seinfo tag taken from a matched
-     * policy. All signature based policy stanzas are consulted and, if no match is
-     * found, the default seinfo label of 'default' (set in ApplicationInfo object) is
-     * used. The security label is attached to the ApplicationInfo instance of the package
-     * in the event that a matching policy was found.
+     * Selects a security label to a package based on input parameters and the seinfo tag taken
+     * from a matched policy. All signature based policy stanzas are consulted and, if no match
+     * is found, the default seinfo label of 'default' is used. The security label is attached to
+     * the ApplicationInfo instance of the package.
      *
      * @param pkg object representing the package to be labeled.
+     * @param isPrivileged boolean.
+     * @param targetSandboxVersion int.
+     * @param targetSdkVersion int. If this pkg runs as a sharedUser, targetSdkVersion is the
+     *        greater of: lowest targetSdk for all pkgs in the sharedUser, or
+     *        MINIMUM_TARGETSDKVERSION.
+     * @return String representing the resulting seinfo.
      */
-    public static void assignSeInfoValue(PackageParser.Package pkg, boolean isPrivileged,
-            int targetSdkVersion) {
+    public static String getSeInfo(PackageParser.Package pkg, boolean isPrivileged,
+            int targetSandboxVersion, int targetSdkVersion) {
+        String seInfo = null;
         synchronized (sPolicies) {
             if (!sPolicyRead) {
                 if (DEBUG_POLICY) {
                     Slog.d(TAG, "Policy not read");
                 }
-                return;
-            }
-            for (Policy policy : sPolicies) {
-                String seInfo = policy.getMatchedSeInfo(pkg);
-                if (seInfo != null) {
-                    pkg.applicationInfo.seInfo = seInfo;
-                    break;
+            } else {
+                for (Policy policy : sPolicies) {
+                    seInfo = policy.getMatchedSeInfo(pkg);
+                    if (seInfo != null) {
+                        break;
+                    }
                 }
             }
         }
 
-        if (pkg.applicationInfo.targetSandboxVersion == 2)
-            pkg.applicationInfo.seInfo += SANDBOX_V2_STR;
-
-        if (isPrivileged) {
-            pkg.applicationInfo.seInfo += PRIVILEGED_APP_STR;
+        if (seInfo == null) {
+            seInfo = DEFAULT_SEINFO;
         }
 
-        pkg.applicationInfo.seInfo += TARGETSDKVERSION_STR + targetSdkVersion;
+        if (targetSandboxVersion == 2) {
+            seInfo += SANDBOX_V2_STR;
+        }
+
+        if (isPrivileged) {
+            seInfo += PRIVILEGED_APP_STR;
+        }
+
+        seInfo += TARGETSDKVERSION_STR + targetSdkVersion;
 
         if (DEBUG_POLICY_INSTALL) {
             Slog.i(TAG, "package (" + pkg.packageName + ") labeled with " +
-                    "seinfo=" + pkg.applicationInfo.seInfo);
+                    "seinfo=" + seInfo);
         }
+        return seInfo;
     }
 }
 
diff --git a/services/core/java/com/android/server/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java
index 2446131..1d9afd9 100644
--- a/services/core/java/com/android/server/pm/SharedUserSetting.java
+++ b/services/core/java/com/android/server/pm/SharedUserSetting.java
@@ -39,6 +39,10 @@
     int uidFlags;
     int uidPrivateFlags;
 
+    // The lowest targetSdkVersion of all apps in the sharedUserSetting, used to assign seinfo so
+    // that all apps within the sharedUser run in the same selinux context.
+    int seInfoTargetSdkVersion;
+
     final ArraySet<PackageSetting> packages = new ArraySet<PackageSetting>();
 
     final PackageSignatures signatures = new PackageSignatures();
@@ -84,6 +88,11 @@
     }
 
     void addPackage(PackageSetting packageSetting) {
+        // If this is the first package added to this shared user, temporarily (until next boot) use
+        // its targetSdkVersion when assigning seInfo for the shared user.
+        if ((packages.size() == 0) && (packageSetting.pkg != null)) {
+            seInfoTargetSdkVersion = packageSetting.pkg.applicationInfo.targetSdkVersion;
+        }
         if (packages.add(packageSetting)) {
             setFlags(this.pkgFlags | packageSetting.pkgFlags);
             setPrivateFlags(this.pkgPrivateFlags | packageSetting.pkgPrivateFlags);
@@ -107,4 +116,26 @@
     public boolean isPrivileged() {
         return (this.pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
     }
+
+    /**
+     * Determine the targetSdkVersion for a sharedUser and update pkg.applicationInfo.seInfo
+     * to ensure that all apps within the sharedUser share an SELinux domain. Use the lowest
+     * targetSdkVersion of all apps within the shared user, which corresponds to the least
+     * restrictive selinux domain.
+     */
+    public void fixSeInfoLocked() {
+        final List<PackageParser.Package> pkgList = getPackages();
+
+        for (PackageParser.Package pkg : pkgList) {
+            if (pkg.applicationInfo.targetSdkVersion < seInfoTargetSdkVersion) {
+                seInfoTargetSdkVersion = pkg.applicationInfo.targetSdkVersion;
+            }
+        }
+        for (PackageParser.Package pkg : pkgList) {
+            final boolean isPrivileged = isPrivileged() | pkg.isPrivileged();
+            pkg.applicationInfo.seInfo = SELinuxMMAC.getSeInfo(pkg, isPrivileged,
+                pkg.applicationInfo.targetSandboxVersion, seInfoTargetSdkVersion);
+        }
+    }
+
 }
diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
index 2ece2b2..062a6b8 100644
--- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java
+++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
@@ -203,8 +203,6 @@
             Slog.w(TAG, "Could not open snapshot profile for " + packageName + ":"
                     + snapshotProfile, e);
             postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR);
-        } finally {
-            IoUtils.closeQuietly(fd);
         }
     }
 
@@ -283,6 +281,8 @@
             } catch (RemoteException e) {
                 Slog.w(TAG,
                         "Failed to call onSuccess after profile snapshot for " + packageName, e);
+            } finally {
+                IoUtils.closeQuietly(fd);
             }
         });
     }
diff --git a/services/core/java/com/android/server/policy/GlobalActions.java b/services/core/java/com/android/server/policy/GlobalActions.java
index 108b6b2..e146135 100644
--- a/services/core/java/com/android/server/policy/GlobalActions.java
+++ b/services/core/java/com/android/server/policy/GlobalActions.java
@@ -20,33 +20,33 @@
 
 import com.android.server.LocalServices;
 import com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs;
-import com.android.server.statusbar.StatusBarManagerInternal;
-import com.android.server.statusbar.StatusBarManagerInternal.GlobalActionsListener;
+import com.android.server.policy.GlobalActionsProvider;
 
-class GlobalActions implements GlobalActionsListener {
+class GlobalActions implements GlobalActionsProvider.GlobalActionsListener {
 
     private static final String TAG = "GlobalActions";
     private static final boolean DEBUG = false;
 
     private final Context mContext;
-    private final StatusBarManagerInternal mStatusBarInternal;
+    private final GlobalActionsProvider mGlobalActionsProvider;
     private final Handler mHandler;
     private final WindowManagerFuncs mWindowManagerFuncs;
     private LegacyGlobalActions mLegacyGlobalActions;
     private boolean mKeyguardShowing;
     private boolean mDeviceProvisioned;
-    private boolean mStatusBarConnected;
+    private boolean mGlobalActionsAvailable;
     private boolean mShowing;
 
     public GlobalActions(Context context, WindowManagerFuncs windowManagerFuncs) {
         mContext = context;
         mHandler = new Handler();
         mWindowManagerFuncs = windowManagerFuncs;
-        mStatusBarInternal = LocalServices.getService(StatusBarManagerInternal.class);
 
-        // Some form factors do not have a status bar.
-        if (mStatusBarInternal != null) {
-            mStatusBarInternal.setGlobalActionsListener(this);
+        mGlobalActionsProvider = LocalServices.getService(GlobalActionsProvider.class);
+        if (mGlobalActionsProvider != null) {
+            mGlobalActionsProvider.setGlobalActionsListener(this);
+        } else {
+            Slog.i(TAG, "No GlobalActionsProvider found, defaulting to LegacyGlobalActions");
         }
     }
 
@@ -58,15 +58,15 @@
 
     public void showDialog(boolean keyguardShowing, boolean deviceProvisioned) {
         if (DEBUG) Slog.d(TAG, "showDialog " + keyguardShowing + " " + deviceProvisioned);
-        if (mStatusBarInternal != null && mStatusBarInternal.isGlobalActionsDisabled()) {
+        if (mGlobalActionsProvider != null && mGlobalActionsProvider.isGlobalActionsDisabled()) {
             return;
         }
         mKeyguardShowing = keyguardShowing;
         mDeviceProvisioned = deviceProvisioned;
         mShowing = true;
-        if (mStatusBarConnected) {
-            mStatusBarInternal.showGlobalActions();
+        if (mGlobalActionsAvailable) {
             mHandler.postDelayed(mShowTimeout, 5000);
+            mGlobalActionsProvider.showGlobalActions();
         } else {
             // SysUI isn't alive, show legacy menu.
             ensureLegacyCreated();
@@ -88,11 +88,12 @@
     }
 
     @Override
-    public void onStatusBarConnectedChanged(boolean connected) {
-        if (DEBUG) Slog.d(TAG, "onStatusBarConnectedChanged " + connected);
-        mStatusBarConnected = connected;
-        if (mShowing && !mStatusBarConnected) {
-            // Status bar died but we need to be showing global actions still, show the legacy.
+    public void onGlobalActionsAvailableChanged(boolean available) {
+        if (DEBUG) Slog.d(TAG, "onGlobalActionsAvailableChanged " + available);
+        mGlobalActionsAvailable = available;
+        if (mShowing && !mGlobalActionsAvailable) {
+            // Global actions provider died but we need to be showing global actions still, show the
+            // legacy global acrions provider.
             ensureLegacyCreated();
             mLegacyGlobalActions.showDialog(mKeyguardShowing, mDeviceProvisioned);
         }
diff --git a/services/core/java/com/android/server/policy/GlobalActionsProvider.java b/services/core/java/com/android/server/policy/GlobalActionsProvider.java
new file mode 100644
index 0000000..d414314
--- /dev/null
+++ b/services/core/java/com/android/server/policy/GlobalActionsProvider.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.policy;
+
+/** Used with LocalServices to add custom handling to global actions. */
+public interface GlobalActionsProvider {
+    /** @return {@code true} if the dialog is enabled. */
+    boolean isGlobalActionsDisabled();
+    /** Set the listener that will handle various global actions evetns. */
+    void setGlobalActionsListener(GlobalActionsListener listener);
+    /** Show the global actions UI to the user. */
+    void showGlobalActions();
+
+    /** Listener to pass global actions events back to system. */
+    public interface GlobalActionsListener {
+        /**
+         * Called when sysui starts and connects its status bar, or when the status bar binder
+         * dies indicating sysui is no longer alive.
+         */
+        void onGlobalActionsAvailableChanged(boolean available);
+
+        /**
+         * Callback from sysui to notify system that global actions has been successfully shown.
+         */
+        void onGlobalActionsShown();
+
+        /**
+         * Callback from sysui to notify system that the user has dismissed global actions and
+         * it no longer needs to be displayed (even if sysui dies).
+         */
+        void onGlobalActionsDismissed();
+    }
+}
diff --git a/services/core/java/com/android/server/policy/LegacyGlobalActions.java b/services/core/java/com/android/server/policy/LegacyGlobalActions.java
index 96d062d..9cb2441 100644
--- a/services/core/java/com/android/server/policy/LegacyGlobalActions.java
+++ b/services/core/java/com/android/server/policy/LegacyGlobalActions.java
@@ -17,18 +17,24 @@
 package com.android.server.policy;
 
 import com.android.internal.app.AlertController;
-import com.android.internal.app.AlertController.AlertParams;
+import com.android.internal.globalactions.Action;
+import com.android.internal.globalactions.ActionsAdapter;
+import com.android.internal.globalactions.ActionsDialog;
+import com.android.internal.globalactions.LongPressAction;
+import com.android.internal.globalactions.SinglePressAction;
+import com.android.internal.globalactions.ToggleAction;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.util.EmergencyAffordanceManager;
+import com.android.internal.R;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.TelephonyProperties;
-import com.android.internal.R;
+import com.android.internal.util.EmergencyAffordanceManager;
 import com.android.internal.widget.LockPatternUtils;
+import com.android.server.policy.PowerAction;
+import com.android.server.policy.RestartAction;
 import com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs;
 
 import android.app.ActivityManager;
-import android.app.Dialog;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.DialogInterface;
@@ -40,7 +46,6 @@
 import android.media.AudioManager;
 import android.net.ConnectivityManager;
 import android.os.Build;
-import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
 import android.os.RemoteException;
@@ -55,23 +60,14 @@
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
-import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
-import android.util.TypedValue;
-import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
-import android.view.accessibility.AccessibilityEvent;
 import android.widget.AdapterView;
-import android.widget.BaseAdapter;
-import android.widget.ImageView;
-import android.widget.ImageView.ScaleType;
-import android.widget.ListView;
-import android.widget.TextView;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -107,12 +103,12 @@
     private final Runnable mOnDismiss;
 
     private ArrayList<Action> mItems;
-    private GlobalActionsDialog mDialog;
+    private ActionsDialog mDialog;
 
     private Action mSilentModeAction;
     private ToggleAction mAirplaneModeOn;
 
-    private MyAdapter mAdapter;
+    private ActionsAdapter mAdapter;
 
     private boolean mKeyguardShowing = false;
     private boolean mDeviceProvisioned = false;
@@ -217,7 +213,7 @@
      * Create the global actions dialog.
      * @return A new dialog.
      */
-    private GlobalActionsDialog createDialog() {
+    private ActionsDialog createDialog() {
         // Simple toggle style if there's no vibrator, otherwise use a tri-state
         if (!mHasVibrator) {
             mSilentModeAction = new SilentModeToggleAction();
@@ -232,7 +228,7 @@
                 R.string.global_actions_airplane_mode_off_status) {
 
             @Override
-            void onToggle(boolean on) {
+            public void onToggle(boolean on) {
                 if (mHasTelephony && Boolean.parseBoolean(
                         SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE))) {
                     mIsWaitingForEcmExit = true;
@@ -282,7 +278,7 @@
                 continue;
             }
             if (GLOBAL_ACTION_KEY_POWER.equals(actionKey)) {
-                mItems.add(new PowerAction());
+                mItems.add(new PowerAction(mContext, mWindowManagerFuncs));
             } else if (GLOBAL_ACTION_KEY_AIRPLANE.equals(actionKey)) {
                 mItems.add(mAirplaneModeOn);
             } else if (GLOBAL_ACTION_KEY_BUGREPORT.equals(actionKey)) {
@@ -307,7 +303,7 @@
             } else if (GLOBAL_ACTION_KEY_ASSIST.equals(actionKey)) {
                 mItems.add(getAssistAction());
             } else if (GLOBAL_ACTION_KEY_RESTART.equals(actionKey)) {
-                mItems.add(new RestartAction());
+                mItems.add(new RestartAction(mContext, mWindowManagerFuncs));
             } else {
                 Log.e(TAG, "Invalid global action key " + actionKey);
             }
@@ -319,14 +315,15 @@
             mItems.add(getEmergencyAction());
         }
 
-        mAdapter = new MyAdapter();
+        mAdapter = new ActionsAdapter(mContext, mItems,
+                () -> mDeviceProvisioned, () -> mKeyguardShowing);
 
-        AlertParams params = new AlertParams(mContext);
+        AlertController.AlertParams params = new AlertController.AlertParams(mContext);
         params.mAdapter = mAdapter;
         params.mOnClickListener = this;
         params.mForceInverseBackground = true;
 
-        GlobalActionsDialog dialog = new GlobalActionsDialog(mContext, params);
+        ActionsDialog dialog = new ActionsDialog(mContext, params);
         dialog.setCanceledOnTouchOutside(false); // Handled by the custom class.
 
         dialog.getListView().setItemsCanFocus(true);
@@ -350,71 +347,6 @@
         return dialog;
     }
 
-    private final class PowerAction extends SinglePressAction implements LongPressAction {
-        private PowerAction() {
-            super(com.android.internal.R.drawable.ic_lock_power_off,
-                R.string.global_action_power_off);
-        }
-
-        @Override
-        public boolean onLongPress() {
-            UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
-            if (!um.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {
-                mWindowManagerFuncs.rebootSafeMode(true);
-                return true;
-            }
-            return false;
-        }
-
-        @Override
-        public boolean showDuringKeyguard() {
-            return true;
-        }
-
-        @Override
-        public boolean showBeforeProvisioning() {
-            return true;
-        }
-
-        @Override
-        public void onPress() {
-            // shutdown by making sure radio and power are handled accordingly.
-            mWindowManagerFuncs.shutdown(false /* confirm */);
-        }
-    }
-
-    private final class RestartAction extends SinglePressAction implements LongPressAction {
-        private RestartAction() {
-            super(R.drawable.ic_restart, R.string.global_action_restart);
-        }
-
-        @Override
-        public boolean onLongPress() {
-            UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
-            if (!um.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {
-                mWindowManagerFuncs.rebootSafeMode(true);
-                return true;
-            }
-            return false;
-        }
-
-        @Override
-        public boolean showDuringKeyguard() {
-            return true;
-        }
-
-        @Override
-        public boolean showBeforeProvisioning() {
-            return true;
-        }
-
-        @Override
-        public void onPress() {
-            mWindowManagerFuncs.reboot(false /* confirm */);
-        }
-    }
-
-
     private class BugReportAction extends SinglePressAction implements LongPressAction {
 
         public BugReportAction() {
@@ -693,330 +625,12 @@
         mAdapter.getItem(which).onPress();
     }
 
-    /**
-     * The adapter used for the list within the global actions dialog, taking
-     * into account whether the keyguard is showing via
-     * {@link LegacyGlobalActions#mKeyguardShowing} and whether the device is provisioned
-     * via {@link LegacyGlobalActions#mDeviceProvisioned}.
-     */
-    private class MyAdapter extends BaseAdapter {
-
-        @Override
-        public int getCount() {
-            int count = 0;
-
-            for (int i = 0; i < mItems.size(); i++) {
-                final Action action = mItems.get(i);
-
-                if (mKeyguardShowing && !action.showDuringKeyguard()) {
-                    continue;
-                }
-                if (!mDeviceProvisioned && !action.showBeforeProvisioning()) {
-                    continue;
-                }
-                count++;
-            }
-            return count;
-        }
-
-        @Override
-        public boolean isEnabled(int position) {
-            return getItem(position).isEnabled();
-        }
-
-        @Override
-        public boolean areAllItemsEnabled() {
-            return false;
-        }
-
-        @Override
-        public Action getItem(int position) {
-
-            int filteredPos = 0;
-            for (int i = 0; i < mItems.size(); i++) {
-                final Action action = mItems.get(i);
-                if (mKeyguardShowing && !action.showDuringKeyguard()) {
-                    continue;
-                }
-                if (!mDeviceProvisioned && !action.showBeforeProvisioning()) {
-                    continue;
-                }
-                if (filteredPos == position) {
-                    return action;
-                }
-                filteredPos++;
-            }
-
-            throw new IllegalArgumentException("position " + position
-                    + " out of range of showable actions"
-                    + ", filtered count=" + getCount()
-                    + ", keyguardshowing=" + mKeyguardShowing
-                    + ", provisioned=" + mDeviceProvisioned);
-        }
-
-        @Override
-        public long getItemId(int position) {
-            return position;
-        }
-
-        @Override
-        public View getView(int position, View convertView, ViewGroup parent) {
-            Action action = getItem(position);
-            return action.create(mContext, convertView, parent, LayoutInflater.from(mContext));
-        }
-    }
-
     // note: the scheme below made more sense when we were planning on having
     // 8 different things in the global actions dialog.  seems overkill with
     // only 3 items now, but may as well keep this flexible approach so it will
     // be easy should someone decide at the last minute to include something
     // else, such as 'enable wifi', or 'enable bluetooth'
 
-    /**
-     * What each item in the global actions dialog must be able to support.
-     */
-    private interface Action {
-        /**
-         * @return Text that will be announced when dialog is created.  null
-         *     for none.
-         */
-        CharSequence getLabelForAccessibility(Context context);
-
-        View create(Context context, View convertView, ViewGroup parent, LayoutInflater inflater);
-
-        void onPress();
-
-        /**
-         * @return whether this action should appear in the dialog when the keygaurd
-         *    is showing.
-         */
-        boolean showDuringKeyguard();
-
-        /**
-         * @return whether this action should appear in the dialog before the
-         *   device is provisioned.
-         */
-        boolean showBeforeProvisioning();
-
-        boolean isEnabled();
-    }
-
-    /**
-     * An action that also supports long press.
-     */
-    private interface LongPressAction extends Action {
-        boolean onLongPress();
-    }
-
-    /**
-     * A single press action maintains no state, just responds to a press
-     * and takes an action.
-     */
-    private static abstract class SinglePressAction implements Action {
-        private final int mIconResId;
-        private final Drawable mIcon;
-        private final int mMessageResId;
-        private final CharSequence mMessage;
-
-        protected SinglePressAction(int iconResId, int messageResId) {
-            mIconResId = iconResId;
-            mMessageResId = messageResId;
-            mMessage = null;
-            mIcon = null;
-        }
-
-        protected SinglePressAction(int iconResId, Drawable icon, CharSequence message) {
-            mIconResId = iconResId;
-            mMessageResId = 0;
-            mMessage = message;
-            mIcon = icon;
-        }
-
-        @Override
-        public boolean isEnabled() {
-            return true;
-        }
-
-        public String getStatus() {
-            return null;
-        }
-
-        @Override
-        abstract public void onPress();
-
-        @Override
-        public CharSequence getLabelForAccessibility(Context context) {
-            if (mMessage != null) {
-                return mMessage;
-            } else {
-                return context.getString(mMessageResId);
-            }
-        }
-
-        @Override
-        public View create(
-                Context context, View convertView, ViewGroup parent, LayoutInflater inflater) {
-            View v = inflater.inflate(R.layout.global_actions_item, parent, false);
-
-            ImageView icon = (ImageView) v.findViewById(R.id.icon);
-            TextView messageView = (TextView) v.findViewById(R.id.message);
-
-            TextView statusView = (TextView) v.findViewById(R.id.status);
-            final String status = getStatus();
-            if (!TextUtils.isEmpty(status)) {
-                statusView.setText(status);
-            } else {
-                statusView.setVisibility(View.GONE);
-            }
-            if (mIcon != null) {
-                icon.setImageDrawable(mIcon);
-                icon.setScaleType(ScaleType.CENTER_CROP);
-            } else if (mIconResId != 0) {
-                icon.setImageDrawable(context.getDrawable(mIconResId));
-            }
-            if (mMessage != null) {
-                messageView.setText(mMessage);
-            } else {
-                messageView.setText(mMessageResId);
-            }
-
-            return v;
-        }
-    }
-
-    /**
-     * A toggle action knows whether it is on or off, and displays an icon
-     * and status message accordingly.
-     */
-    private static abstract class ToggleAction implements Action {
-
-        enum State {
-            Off(false),
-            TurningOn(true),
-            TurningOff(true),
-            On(false);
-
-            private final boolean inTransition;
-
-            State(boolean intermediate) {
-                inTransition = intermediate;
-            }
-
-            public boolean inTransition() {
-                return inTransition;
-            }
-        }
-
-        protected State mState = State.Off;
-
-        // prefs
-        protected int mEnabledIconResId;
-        protected int mDisabledIconResid;
-        protected int mMessageResId;
-        protected int mEnabledStatusMessageResId;
-        protected int mDisabledStatusMessageResId;
-
-        /**
-         * @param enabledIconResId The icon for when this action is on.
-         * @param disabledIconResid The icon for when this action is off.
-         * @param message The general information message, e.g 'Silent Mode'
-         * @param enabledStatusMessageResId The on status message, e.g 'sound disabled'
-         * @param disabledStatusMessageResId The off status message, e.g. 'sound enabled'
-         */
-        public ToggleAction(int enabledIconResId,
-                int disabledIconResid,
-                int message,
-                int enabledStatusMessageResId,
-                int disabledStatusMessageResId) {
-            mEnabledIconResId = enabledIconResId;
-            mDisabledIconResid = disabledIconResid;
-            mMessageResId = message;
-            mEnabledStatusMessageResId = enabledStatusMessageResId;
-            mDisabledStatusMessageResId = disabledStatusMessageResId;
-        }
-
-        /**
-         * Override to make changes to resource IDs just before creating the
-         * View.
-         */
-        void willCreate() {
-
-        }
-
-        @Override
-        public CharSequence getLabelForAccessibility(Context context) {
-            return context.getString(mMessageResId);
-        }
-
-        @Override
-        public View create(Context context, View convertView, ViewGroup parent,
-                LayoutInflater inflater) {
-            willCreate();
-
-            View v = inflater.inflate(R
-                            .layout.global_actions_item, parent, false);
-
-            ImageView icon = (ImageView) v.findViewById(R.id.icon);
-            TextView messageView = (TextView) v.findViewById(R.id.message);
-            TextView statusView = (TextView) v.findViewById(R.id.status);
-            final boolean enabled = isEnabled();
-
-            if (messageView != null) {
-                messageView.setText(mMessageResId);
-                messageView.setEnabled(enabled);
-            }
-
-            boolean on = ((mState == State.On) || (mState == State.TurningOn));
-            if (icon != null) {
-                icon.setImageDrawable(context.getDrawable(
-                        (on ? mEnabledIconResId : mDisabledIconResid)));
-                icon.setEnabled(enabled);
-            }
-
-            if (statusView != null) {
-                statusView.setText(on ? mEnabledStatusMessageResId : mDisabledStatusMessageResId);
-                statusView.setVisibility(View.VISIBLE);
-                statusView.setEnabled(enabled);
-            }
-            v.setEnabled(enabled);
-
-            return v;
-        }
-
-        @Override
-        public final void onPress() {
-            if (mState.inTransition()) {
-                Log.w(TAG, "shouldn't be able to toggle when in transition");
-                return;
-            }
-
-            final boolean nowOn = !(mState == State.On);
-            onToggle(nowOn);
-            changeStateFromPress(nowOn);
-        }
-
-        @Override
-        public boolean isEnabled() {
-            return !mState.inTransition();
-        }
-
-        /**
-         * Implementations may override this if their state can be in on of the intermediate
-         * states until some notification is received (e.g airplane mode is 'turning off' until
-         * we know the wireless connections are back online
-         * @param buttonOn Whether the button was turned on or off
-         */
-        protected void changeStateFromPress(boolean buttonOn) {
-            mState = buttonOn ? State.On : State.Off;
-        }
-
-        abstract void onToggle(boolean on);
-
-        public void updateState(State state) {
-            mState = state;
-        }
-    }
-
     private class SilentModeToggleAction extends ToggleAction {
         public SilentModeToggleAction() {
             super(R.drawable.ic_audio_vol_mute,
@@ -1027,7 +641,7 @@
         }
 
         @Override
-        void onToggle(boolean on) {
+        public void onToggle(boolean on) {
             if (on) {
                 mAudioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
             } else {
@@ -1226,71 +840,4 @@
             mAirplaneState = on ? ToggleAction.State.On : ToggleAction.State.Off;
         }
     }
-
-    private static final class GlobalActionsDialog extends Dialog implements DialogInterface {
-        private final Context mContext;
-        private final AlertController mAlert;
-        private final MyAdapter mAdapter;
-
-        public GlobalActionsDialog(Context context, AlertParams params) {
-            super(context, getDialogTheme(context));
-            mContext = getContext();
-            mAlert = AlertController.create(mContext, this, getWindow());
-            mAdapter = (MyAdapter) params.mAdapter;
-            params.apply(mAlert);
-        }
-
-        private static int getDialogTheme(Context context) {
-            TypedValue outValue = new TypedValue();
-            context.getTheme().resolveAttribute(com.android.internal.R.attr.alertDialogTheme,
-                    outValue, true);
-            return outValue.resourceId;
-        }
-
-        @Override
-        protected void onStart() {
-            super.setCanceledOnTouchOutside(true);
-            super.onStart();
-        }
-
-        public ListView getListView() {
-            return mAlert.getListView();
-        }
-
-        @Override
-        protected void onCreate(Bundle savedInstanceState) {
-            super.onCreate(savedInstanceState);
-            mAlert.installContent();
-        }
-
-        @Override
-        public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
-            if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
-                for (int i = 0; i < mAdapter.getCount(); ++i) {
-                    CharSequence label =
-                            mAdapter.getItem(i).getLabelForAccessibility(getContext());
-                    if (label != null) {
-                        event.getText().add(label);
-                    }
-                }
-            }
-            return super.dispatchPopulateAccessibilityEvent(event);
-        }
-
-        @Override
-        public boolean onKeyDown(int keyCode, KeyEvent event) {
-            if (mAlert.onKeyDown(keyCode, event)) {
-                return true;
-            }
-            return super.onKeyDown(keyCode, event);
-        }
-
-        @Override
-        public boolean onKeyUp(int keyCode, KeyEvent event) {
-            if (mAlert.onKeyUp(keyCode, event)) {
-                return true;
-            }
-            return super.onKeyUp(keyCode, event);
-        }
-    }
 }
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index eaa17ca..ab0779b 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -541,6 +541,7 @@
     volatile boolean mGoingToSleep;
     volatile boolean mRequestedOrGoingToSleep;
     volatile boolean mRecentsVisible;
+    volatile boolean mNavBarVirtualKeyHapticFeedbackEnabled;
     volatile boolean mPictureInPictureVisible;
     // Written by vr manager thread, only read in this class.
     volatile private boolean mPersistentVrModeEnabled;
@@ -4368,6 +4369,11 @@
     }
 
     @Override
+    public void setNavBarVirtualKeyHapticFeedbackEnabledLw(boolean enabled) {
+        mNavBarVirtualKeyHapticFeedbackEnabled = enabled;
+    }
+
+    @Override
     public int adjustSystemUiVisibilityLw(int visibility) {
         mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
         mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
@@ -5892,8 +5898,12 @@
             return result;
         }
 
+        // Enable haptics if down and virtual key without multiple repetitions. If this is a hard
+        // virtual key such as a navigation bar button, only vibrate if flag is enabled.
+        final boolean isNavBarVirtKey = ((event.getFlags() & KeyEvent.FLAG_VIRTUAL_HARD_KEY) != 0);
         boolean useHapticFeedback = down
                 && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
+                && (!isNavBarVirtKey || mNavBarVirtualKeyHapticFeedbackEnabled)
                 && event.getRepeatCount() == 0;
 
         // Handle special keys.
diff --git a/services/core/java/com/android/server/policy/PowerAction.java b/services/core/java/com/android/server/policy/PowerAction.java
new file mode 100644
index 0000000..d2de58e
--- /dev/null
+++ b/services/core/java/com/android/server/policy/PowerAction.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.policy;
+
+import android.content.Context;
+import android.os.UserManager;
+import com.android.internal.globalactions.LongPressAction;
+import com.android.internal.globalactions.SinglePressAction;
+import com.android.internal.R;
+import com.android.server.policy.WindowManagerPolicy;
+
+public final class PowerAction extends SinglePressAction implements LongPressAction {
+    private final Context mContext;
+    private final WindowManagerPolicy.WindowManagerFuncs mWindowManagerFuncs;
+
+    public PowerAction(Context context,
+            WindowManagerPolicy.WindowManagerFuncs windowManagerFuncs) {
+        super(R.drawable.ic_lock_power_off, R.string.global_action_power_off);
+        mContext = context;
+        mWindowManagerFuncs = windowManagerFuncs;
+    }
+
+    @Override
+    public boolean onLongPress() {
+        UserManager um = mContext.getSystemService(UserManager.class);
+        if (!um.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {
+            mWindowManagerFuncs.rebootSafeMode(true);
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean showDuringKeyguard() {
+        return true;
+    }
+
+    @Override
+    public boolean showBeforeProvisioning() {
+        return true;
+    }
+
+    @Override
+    public void onPress() {
+        // shutdown by making sure radio and power are handled accordingly.
+        mWindowManagerFuncs.shutdown(false /* confirm */);
+    }
+}
diff --git a/services/core/java/com/android/server/policy/RestartAction.java b/services/core/java/com/android/server/policy/RestartAction.java
new file mode 100644
index 0000000..0f13da8
--- /dev/null
+++ b/services/core/java/com/android/server/policy/RestartAction.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.policy;
+
+import android.content.Context;
+import android.os.UserManager;
+import com.android.internal.globalactions.LongPressAction;
+import com.android.internal.globalactions.SinglePressAction;
+import com.android.internal.R;
+import com.android.server.policy.WindowManagerPolicy;
+
+public final class RestartAction extends SinglePressAction implements LongPressAction {
+    private final Context mContext;
+    private final WindowManagerPolicy.WindowManagerFuncs mWindowManagerFuncs;
+
+    public RestartAction(Context context,
+            WindowManagerPolicy.WindowManagerFuncs windowManagerFuncs) {
+        super(R.drawable.ic_restart, R.string.global_action_restart);
+        mContext = context;
+        mWindowManagerFuncs = windowManagerFuncs;
+    }
+
+    @Override
+    public boolean onLongPress() {
+        UserManager um = mContext.getSystemService(UserManager.class);
+        if (!um.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {
+            mWindowManagerFuncs.rebootSafeMode(true);
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean showDuringKeyguard() {
+        return true;
+    }
+
+    @Override
+    public boolean showBeforeProvisioning() {
+        return true;
+    }
+
+    @Override
+    public void onPress() {
+        mWindowManagerFuncs.reboot(false /* confirm */);
+    }
+}
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index a07f5eb..ab331a5 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -1531,6 +1531,11 @@
     void setPipVisibilityLw(boolean visible);
 
     /**
+     * Called by System UI to enable or disable haptic feedback on the navigation bar buttons.
+     */
+    void setNavBarVirtualKeyHapticFeedbackEnabledLw(boolean enabled);
+
+    /**
      * Specifies whether there is an on-screen navigation bar separate from the status bar.
      */
     public boolean hasNavigationBar();
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index 3ab771b..095eaa5 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -79,10 +79,6 @@
 
     void setCurrentUser(int newUserId);
 
-    boolean isGlobalActionsDisabled();
-    void setGlobalActionsListener(GlobalActionsListener listener);
-    void showGlobalActions();
-
     /**
      * Set whether the top app currently hides the statusbar.
      *
@@ -98,23 +94,4 @@
      * @param rotation rotation suggestion
      */
     void onProposedRotationChanged(int rotation, boolean isValid);
-
-    public interface GlobalActionsListener {
-        /**
-         * Called when sysui starts and connects its status bar, or when the status bar binder
-         * dies indicating sysui is no longer alive.
-         */
-        void onStatusBarConnectedChanged(boolean connected);
-
-        /**
-         * Callback from sysui to notify system that global actions has been successfully shown.
-         */
-        void onGlobalActionsShown();
-
-        /**
-         * Callback from sysui to notify system that the user has dismissed global actions and
-         * it no longer needs to be displayed (even if sysui dies).
-         */
-        void onGlobalActionsDismissed();
-    }
 }
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 343fb91..59fce64 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -47,8 +47,8 @@
 import com.android.internal.util.DumpUtils;
 import com.android.server.LocalServices;
 import com.android.server.notification.NotificationDelegate;
+import com.android.server.policy.GlobalActionsProvider;
 import com.android.server.power.ShutdownThread;
-import com.android.server.statusbar.StatusBarManagerInternal.GlobalActionsListener;
 import com.android.server.wm.WindowManagerService;
 
 import java.io.FileDescriptor;
@@ -74,7 +74,7 @@
 
     // for disabling the status bar
     private final ArrayList<DisableRecord> mDisableRecords = new ArrayList<DisableRecord>();
-    private GlobalActionsListener mGlobalActionListener;
+    private GlobalActionsProvider.GlobalActionsListener mGlobalActionListener;
     private IBinder mSysUiVisToken = new Binder();
     private int mDisabled1 = 0;
     private int mDisabled2 = 0;
@@ -162,6 +162,7 @@
         mWindowManager = windowManager;
 
         LocalServices.addService(StatusBarManagerInternal.class, mInternalService);
+        LocalServices.addService(GlobalActionsProvider.class, mGlobalActionsProvider);
     }
 
     /**
@@ -375,26 +376,6 @@
         }
 
         @Override
-        public boolean isGlobalActionsDisabled() {
-            return (mDisabled2 & DISABLE2_GLOBAL_ACTIONS) != 0;
-        }
-
-        @Override
-        public void setGlobalActionsListener(GlobalActionsListener listener) {
-            mGlobalActionListener = listener;
-            mGlobalActionListener.onStatusBarConnectedChanged(mBar != null);
-        }
-
-        @Override
-        public void showGlobalActions() {
-            if (mBar != null) {
-                try {
-                    mBar.showGlobalActionsMenu();
-                } catch (RemoteException ex) {}
-            }
-        }
-
-        @Override
         public void setTopAppHidesStatusBar(boolean hidesStatusBar) {
             if (mBar != null) {
                 try {
@@ -427,6 +408,28 @@
         }
     };
 
+    private final GlobalActionsProvider mGlobalActionsProvider = new GlobalActionsProvider() {
+        @Override
+        public boolean isGlobalActionsDisabled() {
+            return (mDisabled2 & DISABLE2_GLOBAL_ACTIONS) != 0;
+        }
+
+        @Override
+        public void setGlobalActionsListener(GlobalActionsProvider.GlobalActionsListener listener) {
+            mGlobalActionListener = listener;
+            mGlobalActionListener.onGlobalActionsAvailableChanged(mBar != null);
+        }
+
+        @Override
+        public void showGlobalActions() {
+            if (mBar != null) {
+                try {
+                    mBar.showGlobalActionsMenu();
+                } catch (RemoteException ex) {}
+            }
+        }
+    };
+
     // ================================================================================
     // From IStatusBarService
     // ================================================================================
@@ -892,7 +895,7 @@
     private void notifyBarAttachChanged() {
         mHandler.post(() -> {
             if (mGlobalActionListener == null) return;
-            mGlobalActionListener.onStatusBarConnectedChanged(mBar != null);
+            mGlobalActionListener.onGlobalActionsAvailableChanged(mBar != null);
         });
     }
 
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 2c3c5d2..94b8518 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -509,14 +509,10 @@
             // on-going notification for the user to control their visibility.
             if (visible) {
                 changed = mAlertWindowSurfaces.add(surfaceController);
-                if (changed) {
-                    MetricsLoggerWrapper.logAppOverlayEnter(mUid, mPackageName, true);
-                }
+                MetricsLoggerWrapper.logAppOverlayEnter(mUid, mPackageName, changed, type, true);
             } else {
                 changed = mAlertWindowSurfaces.remove(surfaceController);
-                if (changed) {
-                    MetricsLoggerWrapper.logAppOverlayExit(mUid, mPackageName, true);
-                }
+                MetricsLoggerWrapper.logAppOverlayExit(mUid, mPackageName, changed, type, true);
             }
 
             if (changed) {
@@ -537,14 +533,10 @@
 
         if (visible) {
             changed = mAppOverlaySurfaces.add(surfaceController);
-            if (changed) {
-                MetricsLoggerWrapper.logAppOverlayEnter(mUid, mPackageName, false);
-            }
+            MetricsLoggerWrapper.logAppOverlayEnter(mUid, mPackageName, changed, type, false);
         } else {
             changed = mAppOverlaySurfaces.remove(surfaceController);
-            if (changed) {
-                MetricsLoggerWrapper.logAppOverlayExit(mUid, mPackageName, false);
-            }
+            MetricsLoggerWrapper.logAppOverlayExit(mUid, mPackageName, changed, type, false);
         }
 
         if (changed) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0c6429a..78c04e8 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -5922,6 +5922,18 @@
         }
     }
 
+    public void setNavBarVirtualKeyHapticFeedbackEnabled(boolean enabled) {
+        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Caller does not hold permission "
+                    + android.Manifest.permission.STATUS_BAR);
+        }
+
+        synchronized (mWindowMap) {
+            mPolicy.setNavBarVirtualKeyHapticFeedbackEnabledLw(enabled);
+        }
+    }
+
     // TODO(multidisplay): StatusBar on multiple screens?
     private boolean updateStatusBarVisibilityLocked(int visibility) {
         if (mLastDispatchedSystemUiVisibility == visibility) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 2f6a6e0..6259926 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -206,6 +206,8 @@
             "com.google.android.clockwork.lefty.WearLeftyService";
     private static final String WEAR_TIME_SERVICE_CLASS =
             "com.google.android.clockwork.time.WearTimeService";
+    private static final String WEAR_GLOBAL_ACTIONS_SERVICE_CLASS =
+            "com.android.clockwork.globalactions.GlobalActionsService";
     private static final String ACCOUNT_SERVICE_CLASS =
             "com.android.server.accounts.AccountManagerService$Lifecycle";
     private static final String CONTENT_SERVICE_CLASS =
@@ -1547,6 +1549,10 @@
                 mSystemServiceManager.startService(WEAR_LEFTY_SERVICE_CLASS);
                 traceEnd();
             }
+
+            traceBeginAndSlog("StartWearGlobalActionsService");
+            mSystemServiceManager.startService(WEAR_GLOBAL_ACTIONS_SERVICE_CLASS);
+            traceEnd();
         }
 
         if (!disableSlices) {
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
index f2f1b10..5b1f5c1 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
@@ -24,7 +24,9 @@
 
 import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
 import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
+import static com.android.server.am.ActivityStack.ActivityState.FINISHING;
 import static com.android.server.am.ActivityStack.ActivityState.INITIALIZING;
+import static com.android.server.am.ActivityStack.ActivityState.PAUSED;
 import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
 import static com.android.server.am.ActivityStack.ActivityState.STOPPED;
 import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING;
@@ -135,6 +137,16 @@
         mActivity.makeVisibleIfNeeded(null /* starting */);
 
         assertTrue(mActivity.isState(INITIALIZING));
+
+        // Make sure the state does not change if we are not the current top activity.
+        mActivity.setState(STOPPED, "testPausingWhenVisibleFromStopped behind");
+
+        // Make sure that the state does not change when we have an activity becoming translucent
+        final ActivityRecord topActivity = new ActivityBuilder(mService).setTask(mTask).build();
+        mStack.mTranslucentActivityWaiting = topActivity;
+        mActivity.makeVisibleIfNeeded(null /* starting */);
+
+        assertTrue(mActivity.isState(STOPPED));
     }
 
     @Test
@@ -218,4 +230,19 @@
         assertTrue(mActivity.isState(DESTROYED));
         assertTrue(mActivity.finishing);
     }
+
+    @Test
+    public void testSetInvalidState() throws Exception {
+        mActivity.setState(DESTROYED, "testInvalidState");
+
+        boolean exceptionEncountered = false;
+
+        try {
+            mActivity.setState(FINISHING, "testInvalidState");
+        } catch (IllegalArgumentException e) {
+            exceptionEncountered = true;
+        }
+
+        assertTrue(exceptionEncountered);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
index a98d5a1..32a29a2 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
@@ -24,6 +24,8 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 
+import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
+import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
 import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
 
 import static org.junit.Assert.assertEquals;
@@ -31,8 +33,13 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
 
-import android.content.ComponentName;
+import android.app.servertransaction.DestroyActivityItem;
 import android.content.pm.ActivityInfo;
 import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
@@ -457,4 +464,26 @@
                 .setCreateTask(true).build();
         return stack;
     }
+
+    @Test
+    public void testSuppressMultipleDestroy() throws Exception {
+        final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build();
+        final ClientLifecycleManager lifecycleManager = mock(ClientLifecycleManager.class);
+        final ProcessRecord app = r.app;
+
+        // The mocked lifecycle manager must be set on the ActivityStackSupervisor's reference to
+        // the service rather than mService as mService is a spy and setting the value will not
+        // propagate as ActivityManagerService hands its own reference to the
+        // ActivityStackSupervisor during construction.
+        ((TestActivityManagerService) mSupervisor.mService).setLifecycleManager(lifecycleManager);
+
+        mStack.destroyActivityLocked(r, true, "first invocation");
+        verify(lifecycleManager, times(1)).scheduleTransaction(eq(app.thread),
+                eq(r.appToken), any(DestroyActivityItem.class));
+        assertTrue(r.isState(DESTROYED, DESTROYING));
+
+        mStack.destroyActivityLocked(r, true, "second invocation");
+        verify(lifecycleManager, times(1)).scheduleTransaction(eq(app.thread),
+                eq(r.appToken), any(DestroyActivityItem.class));
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
index 10253c5..ff7b1d0 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -273,6 +273,8 @@
      * {@link ActivityStackSupervisor}.
      */
     protected static class TestActivityManagerService extends ActivityManagerService {
+        private ClientLifecycleManager mLifecycleManager;
+
         TestActivityManagerService(Context context) {
             super(context);
             mSupportsMultiWindow = true;
@@ -284,6 +286,18 @@
         }
 
         @Override
+        public ClientLifecycleManager getLifecycleManager() {
+            if (mLifecycleManager == null) {
+                return super.getLifecycleManager();
+            }
+            return mLifecycleManager;
+        }
+
+        void setLifecycleManager(ClientLifecycleManager manager) {
+            mLifecycleManager = manager;
+        }
+
+        @Override
         final protected ActivityStackSupervisor createStackSupervisor() {
             final ActivityStackSupervisor supervisor = spy(createTestSupervisor());
 
diff --git a/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java b/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java
index a7e3810..8005bc7 100644
--- a/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java
@@ -16,10 +16,11 @@
 
 package com.android.server.am;
 
-import static com.android.server.am.MemoryStatUtil.parseMemoryStat;
+import static com.android.server.am.MemoryStatUtil.parseMemoryStatFromMemcg;
 import static com.android.server.am.MemoryStatUtil.MemoryStat;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -31,44 +32,44 @@
 @SmallTest
 public class MemoryStatUtilTest {
   private String MEMORY_STAT_CONTENTS = String.join(
-      "\n",
-      "cache 96", // keep different from total_cache to catch reading wrong value
-      "rss 97", // keep different from total_rss to catch reading wrong value
-      "rss_huge 0",
-      "mapped_file 524288",
-      "writeback 0",
-      "swap 95", // keep different from total_rss to catch reading wrong value
-      "pgpgin 16717",
-      "pgpgout 5037",
-      "pgfault 99", // keep different from total_pgfault to catch reading wrong value
-      "pgmajfault 98", // keep different from total_pgmajfault to catch reading wrong value
-      "inactive_anon 503808",
-      "active_anon 46309376",
-      "inactive_file 876544",
-      "active_file 81920",
-      "unevictable 0",
-      "hierarchical_memory_limit 18446744073709551615",
-      "hierarchical_memsw_limit 18446744073709551615",
-      "total_cache 4",
-      "total_rss 3",
-      "total_rss_huge 0",
-      "total_mapped_file 524288",
-      "total_writeback 0",
-      "total_swap 5",
-      "total_pgpgin 16717",
-      "total_pgpgout 5037",
-      "total_pgfault 1",
-      "total_pgmajfault 2",
-      "total_inactive_anon 503808",
-      "total_active_anon 46309376",
-      "total_inactive_file 876544",
-      "total_active_file 81920",
-      "total_unevictable 0");
+          "\n",
+          "cache 96", // keep different from total_cache to catch reading wrong value
+          "rss 97", // keep different from total_rss to catch reading wrong value
+          "rss_huge 0",
+          "mapped_file 524288",
+          "writeback 0",
+          "swap 95", // keep different from total_rss to catch reading wrong value
+          "pgpgin 16717",
+          "pgpgout 5037",
+          "pgfault 99", // keep different from total_pgfault to catch reading wrong value
+          "pgmajfault 98", // keep different from total_pgmajfault to catch reading wrong value
+          "inactive_anon 503808",
+          "active_anon 46309376",
+          "inactive_file 876544",
+          "active_file 81920",
+          "unevictable 0",
+          "hierarchical_memory_limit 18446744073709551615",
+          "hierarchical_memsw_limit 18446744073709551615",
+          "total_cache 4",
+          "total_rss 3",
+          "total_rss_huge 0",
+          "total_mapped_file 524288",
+          "total_writeback 0",
+          "total_swap 5",
+          "total_pgpgin 16717",
+          "total_pgpgout 5037",
+          "total_pgfault 1",
+          "total_pgmajfault 2",
+          "total_inactive_anon 503808",
+          "total_active_anon 46309376",
+          "total_inactive_file 876544",
+          "total_active_file 81920",
+          "total_unevictable 0");
 
 
   @Test
   public void testParseMemoryStat_parsesCorrectValues() throws Exception {
-    MemoryStat stat = parseMemoryStat(MEMORY_STAT_CONTENTS);
+    MemoryStat stat = parseMemoryStatFromMemcg(MEMORY_STAT_CONTENTS);
     assertEquals(stat.pgfault, 1);
     assertEquals(stat.pgmajfault, 2);
     assertEquals(stat.rssInBytes, 3);
@@ -78,18 +79,10 @@
 
   @Test
   public void testParseMemoryStat_emptyMemoryStatContents() throws Exception {
-    MemoryStat stat = parseMemoryStat("");
-    assertEquals(stat.pgfault, 0);
-    assertEquals(stat.pgmajfault, 0);
-    assertEquals(stat.rssInBytes, 0);
-    assertEquals(stat.cacheInBytes, 0);
-    assertEquals(stat.swapInBytes, 0);
+    MemoryStat stat = parseMemoryStatFromMemcg("");
+    assertNull(stat);
 
-    stat = parseMemoryStat(null);
-    assertEquals(stat.pgfault, 0);
-    assertEquals(stat.pgmajfault, 0);
-    assertEquals(stat.rssInBytes, 0);
-    assertEquals(stat.cacheInBytes, 0);
-    assertEquals(stat.swapInBytes, 0);
+    stat = parseMemoryStatFromMemcg(null);
+    assertNull(stat);
   }
 }
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 206ee7a..34c5db3 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -637,6 +637,10 @@
     }
 
     @Override
+    public void setNavBarVirtualKeyHapticFeedbackEnabledLw(boolean enabled) {
+    }
+
+    @Override
     public void onSystemUiStarted() {
     }
 
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 69b2c63..a302578 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -465,6 +465,23 @@
         }
     }
 
+    /**
+     * Called by the Binder stub.
+     */
+    UsageEvents queryEventsForPackage(int userId, long beginTime, long endTime,
+            String packageName) {
+        synchronized (mLock) {
+            final long timeNow = checkAndGetTimeLocked();
+            if (!validRange(timeNow, beginTime, endTime)) {
+                return null;
+            }
+
+            final UserUsageStatsService service =
+                    getUserDataAndInitializeIfNeededLocked(userId, timeNow);
+            return service.queryEventsForPackage(beginTime, endTime, packageName);
+        }
+    }
+
     private static boolean validRange(long currentTime, long beginTime, long endTime) {
         return beginTime <= currentTime && beginTime < endTime;
     }
@@ -661,6 +678,26 @@
         }
 
         @Override
+        public UsageEvents queryEventsForPackage(long beginTime, long endTime,
+                String callingPackage) {
+            final int callingUid = Binder.getCallingUid();
+            final int callingUserId = UserHandle.getUserId(callingUid);
+
+            if (mPackageManagerInternal.getPackageUid(callingPackage, PackageManager.MATCH_ANY_USER,
+                    callingUserId) != callingUid) {
+                throw new SecurityException("Calling uid " + callingPackage + " cannot query events"
+                        + "for package " + callingPackage);
+            }
+            final long token = Binder.clearCallingIdentity();
+            try {
+                return UsageStatsService.this.queryEventsForPackage(callingUserId, beginTime,
+                        endTime, callingPackage);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
         public boolean isAppInactive(String packageName, int userId) {
             try {
                 userId = ActivityManager.getService().handleIncomingUser(Binder.getCallingPid(),
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 7f060b3..29c5ee8 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -355,6 +355,47 @@
         return new UsageEvents(results, table);
     }
 
+    UsageEvents queryEventsForPackage(final long beginTime, final long endTime,
+            final String packageName) {
+        final ArraySet<String> names = new ArraySet<>();
+        names.add(packageName);
+        final List<UsageEvents.Event> results = queryStats(UsageStatsManager.INTERVAL_DAILY,
+                beginTime, endTime, (stats, mutable, accumulatedResult) -> {
+                    if (stats.events == null) {
+                        return;
+                    }
+
+                    final int startIndex = stats.events.closestIndexOnOrAfter(beginTime);
+                    if (startIndex < 0) {
+                        return;
+                    }
+
+                    final int size = stats.events.size();
+                    for (int i = startIndex; i < size; i++) {
+                        if (stats.events.keyAt(i) >= endTime) {
+                            return;
+                        }
+
+                        final UsageEvents.Event event = stats.events.valueAt(i);
+                        if (!packageName.equals(event.mPackage)) {
+                            continue;
+                        }
+                        if (event.mClass != null) {
+                            names.add(event.mClass);
+                        }
+                        accumulatedResult.add(event);
+                    }
+                });
+
+        if (results == null || results.isEmpty()) {
+            return null;
+        }
+
+        final String[] table = names.toArray(new String[names.size()]);
+        Arrays.sort(table);
+        return new UsageEvents(results, table);
+    }
+
     void persistActiveStats() {
         if (mStatsChanged) {
             Slog.i(TAG, mLogPrefix + "Flushing usage stats to disk");
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 96eb23d..f0c120b 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1000,8 +1000,13 @@
             "wfc_emergency_address_carrier_app_string";
 
     /**
-     * Boolean to decide whether to use #KEY_CARRIER_NAME_STRING from CarrierConfig app.
-     * @hide
+     * Unconditionally override the carrier name string using #KEY_CARRIER_NAME_STRING.
+     *
+     * If true, then the carrier display name will be #KEY_CARRIER_NAME_STRING, unconditionally.
+     *
+     * <p>If false, then the override will be performed conditionally and the
+     * #KEY_CARRIER_NAME_STRING will have the lowest-precedence; it will only be used in the event
+     * that the name string would otherwise be empty, allowing it to serve as a last-resort.
      */
     public static final String KEY_CARRIER_NAME_OVERRIDE_BOOL = "carrier_name_override_bool";
 
@@ -1009,7 +1014,6 @@
      * String to identify carrier name in CarrierConfig app. This string overrides SPN if
      * #KEY_CARRIER_NAME_OVERRIDE_BOOL is true; otherwise, it will be used if its value is provided
      * and SPN is unavailable
-     * @hide
      */
     public static final String KEY_CARRIER_NAME_STRING = "carrier_name_string";
 
@@ -1575,6 +1579,14 @@
             "notify_international_call_on_wfc_bool";
 
     /**
+     * Flag specifying whether to show an alert dialog for video call charges.
+     * By default this value is {@code false}.
+     * @hide
+     */
+    public static final String KEY_SHOW_VIDEO_CALL_CHARGES_ALERT_DIALOG_BOOL =
+            "show_video_call_charges_alert_dialog_bool";
+
+    /**
      * An array containing custom call forwarding number prefixes that will be blocked while the
      * device is reporting that it is roaming. By default, there are no custom call
      * forwarding prefixes and none of these numbers will be filtered. If one or more entries are
@@ -2119,6 +2131,7 @@
         sDefaults.putBoolean(KEY_DISPLAY_VOICEMAIL_NUMBER_AS_DEFAULT_CALL_FORWARDING_NUMBER_BOOL,
                 false);
         sDefaults.putBoolean(KEY_NOTIFY_INTERNATIONAL_CALL_ON_WFC_BOOL, false);
+        sDefaults.putBoolean(KEY_SHOW_VIDEO_CALL_CHARGES_ALERT_DIALOG_BOOL, false);
         sDefaults.putStringArray(KEY_CALL_FORWARDING_BLOCKS_WHILE_ROAMING_STRING_ARRAY,
                 null);
         sDefaults.putInt(KEY_LTE_EARFCNS_RSRP_BOOST_INT, 0);
diff --git a/telephony/java/android/telephony/CellIdentityCdma.java b/telephony/java/android/telephony/CellIdentityCdma.java
index 2e1d1dc..105ddb0 100644
--- a/telephony/java/android/telephony/CellIdentityCdma.java
+++ b/telephony/java/android/telephony/CellIdentityCdma.java
@@ -103,8 +103,12 @@
         mNetworkId = nid;
         mSystemId = sid;
         mBasestationId = bid;
-        mLongitude = lon;
-        mLatitude = lat;
+        if (!isNullIsland(lat, lon)) {
+            mLongitude = lon;
+            mLatitude = lat;
+        } else {
+            mLongitude = mLatitude = Integer.MAX_VALUE;
+        }
         mAlphaLong = alphal;
         mAlphaShort = alphas;
     }
@@ -119,6 +123,18 @@
     }
 
     /**
+     * Take the latitude and longitude in 1/4 seconds and see if
+     * the reported location is on Null Island.
+     *
+     * @return whether the reported Lat/Long are for Null Island
+     *
+     * @hide
+     */
+    private boolean isNullIsland(int lat, int lon) {
+        return Math.abs(lat) <= 1 && Math.abs(lon) <= 1;
+    }
+
+    /**
      * @return Network Id 0..65535, Integer.MAX_VALUE if unknown
      */
     public int getNetworkId() {
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
index f948f81..d35eb60 100644
--- a/telephony/java/android/telephony/CellIdentityGsm.java
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -120,7 +120,7 @@
 
     /**
      * @return 3-digit Mobile Country Code, 0..999, Integer.MAX_VALUE if unknown
-     * @deprecated Use {@link #getMccStr} instead.
+     * @deprecated Use {@link #getMccString} instead.
      */
     @Deprecated
     public int getMcc() {
@@ -129,7 +129,7 @@
 
     /**
      * @return 2 or 3-digit Mobile Network Code, 0..999, Integer.MAX_VALUE if unknown
-     * @deprecated Use {@link #getMncStr} instead.
+     * @deprecated Use {@link #getMncString} instead.
      */
     @Deprecated
     public int getMnc() {
@@ -176,14 +176,14 @@
     /**
      * @return Mobile Country Code in string format, null if unknown
      */
-    public String getMccStr() {
+    public String getMccString() {
         return mMccStr;
     }
 
     /**
      * @return Mobile Network Code in string format, null if unknown
      */
-    public String getMncStr() {
+    public String getMncString() {
         return mMncStr;
     }
 
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index 5f1f448..2b8eb5f 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -125,7 +125,7 @@
 
     /**
      * @return 3-digit Mobile Country Code, 0..999, Integer.MAX_VALUE if unknown
-     * @deprecated Use {@link #getMccStr} instead.
+     * @deprecated Use {@link #getMccString} instead.
      */
     @Deprecated
     public int getMcc() {
@@ -134,7 +134,7 @@
 
     /**
      * @return 2 or 3-digit Mobile Network Code, 0..999, Integer.MAX_VALUE if unknown
-     * @deprecated Use {@link #getMncStr} instead.
+     * @deprecated Use {@link #getMncString} instead.
      */
     @Deprecated
     public int getMnc() {
@@ -179,14 +179,14 @@
     /**
      * @return Mobile Country Code in string format, null if unknown
      */
-    public String getMccStr() {
+    public String getMccString() {
         return mMccStr;
     }
 
     /**
      * @return Mobile Network Code in string format, null if unknown
      */
-    public String getMncStr() {
+    public String getMncString() {
         return mMncStr;
     }
 
diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java
index 001d19f..992545d 100644
--- a/telephony/java/android/telephony/CellIdentityTdscdma.java
+++ b/telephony/java/android/telephony/CellIdentityTdscdma.java
@@ -86,7 +86,7 @@
      * Get Mobile Country Code in string format
      * @return Mobile Country Code in string format, null if unknown
      */
-    public String getMccStr() {
+    public String getMccString() {
         return mMccStr;
     }
 
@@ -94,7 +94,7 @@
      * Get Mobile Network Code in string format
      * @return Mobile Network Code in string format, null if unknown
      */
-    public String getMncStr() {
+    public String getMncString() {
         return mMncStr;
     }
 
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index 1aa1715..a5fd7dd 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -118,7 +118,7 @@
 
     /**
      * @return 3-digit Mobile Country Code, 0..999, Integer.MAX_VALUE if unknown
-     * @deprecated Use {@link #getMccStr} instead.
+     * @deprecated Use {@link #getMccString} instead.
      */
     @Deprecated
     public int getMcc() {
@@ -127,7 +127,7 @@
 
     /**
      * @return 2 or 3-digit Mobile Network Code, 0..999, Integer.MAX_VALUE if unknown
-     * @deprecated Use {@link #getMncStr} instead.
+     * @deprecated Use {@link #getMncString} instead.
      */
     @Deprecated
     public int getMnc() {
@@ -160,14 +160,14 @@
     /**
      * @return Mobile Country Code in string version, null if unknown
      */
-    public String getMccStr() {
+    public String getMccString() {
         return mMccStr;
     }
 
     /**
      * @return Mobile Network Code in string version, null if unknown
      */
-    public String getMncStr() {
+    public String getMncString() {
         return mMncStr;
     }
 
diff --git a/telephony/java/android/telephony/CellSignalStrengthCdma.java b/telephony/java/android/telephony/CellSignalStrengthCdma.java
index ece1ee3..183f96d 100644
--- a/telephony/java/android/telephony/CellSignalStrengthCdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthCdma.java
@@ -41,14 +41,36 @@
         setDefaultValues();
     }
 
-    /** @hide */
+    /**
+     * SignalStrength constructor for input from the HAL.
+     *
+     * Note that values received from the HAL require coersion to be compatible here. All values
+     * reported through IRadio are the negative of the actual values (which results in a positive
+     * input to this method.
+     *
+     * <p>Note that this HAL is inconsistent with UMTS-based radio techs as the value indicating
+     * that a field is unreported is negative, rather than a large(r) positive number.
+     * <p>Also note that to keep the public-facing methods of this class consistent with others,
+     * unreported values are coerced to Integer.MAX_VALUE rather than left as -1, which is
+     * a departure from SignalStrength, which is stuck with the values it currently reports.
+     *
+     * @param cdmaDbm negative of the CDMA signal strength value or -1 if invalid.
+     * @param cdmaEcio negative of the CDMA pilot/noise ratio or -1 if invalid.
+     * @param evdoDbm negative of the EvDO signal strength value or -1 if invalid.
+     * @param evdoEcio negative of the EvDO pilot/noise ratio or -1 if invalid.
+     * @param evdoSnr an SNR value 0..8 or -1 if invalid.
+     * @hide
+     */
     public CellSignalStrengthCdma(int cdmaDbm, int cdmaEcio, int evdoDbm, int evdoEcio,
             int evdoSnr) {
-        mCdmaDbm = cdmaDbm;
-        mCdmaEcio = cdmaEcio;
-        mEvdoDbm = evdoDbm;
-        mEvdoEcio = evdoEcio;
-        mEvdoSnr = evdoSnr;
+        // The values here were lifted from SignalStrength.validateInput()
+        // FIXME: Combine all checking and setting logic between this and SignalStrength.
+        mCdmaDbm = ((cdmaDbm > 0) && (cdmaDbm < 120))  ? -cdmaDbm : Integer.MAX_VALUE;
+        mCdmaEcio = ((cdmaEcio > 0) && (cdmaEcio < 160)) ? -cdmaEcio : Integer.MAX_VALUE;
+
+        mEvdoDbm = ((evdoDbm > 0) && (evdoDbm < 120)) ? -evdoDbm : Integer.MAX_VALUE;
+        mEvdoEcio = ((evdoEcio > 0) && (evdoEcio < 160)) ? -evdoEcio : Integer.MAX_VALUE;
+        mEvdoSnr = ((evdoSnr > 0) && (evdoSnr <= 8)) ? evdoSnr : Integer.MAX_VALUE;
     }
 
     /** @hide */
@@ -303,13 +325,10 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         if (DBG) log("writeToParcel(Parcel, int): " + toString());
-        // Need to multiply CdmaDbm, CdmaEcio, EvdoDbm and EvdoEcio by -1
-        // to ensure consistency when reading values written here
-        // unless the value is invalid
-        dest.writeInt(mCdmaDbm * (mCdmaDbm != Integer.MAX_VALUE ? -1 : 1));
-        dest.writeInt(mCdmaEcio * (mCdmaEcio != Integer.MAX_VALUE ? -1 : 1));
-        dest.writeInt(mEvdoDbm * (mEvdoDbm != Integer.MAX_VALUE ? -1 : 1));
-        dest.writeInt(mEvdoEcio * (mEvdoEcio != Integer.MAX_VALUE ? -1 : 1));
+        dest.writeInt(mCdmaDbm);
+        dest.writeInt(mCdmaEcio);
+        dest.writeInt(mEvdoDbm);
+        dest.writeInt(mEvdoEcio);
         dest.writeInt(mEvdoSnr);
     }
 
@@ -322,13 +341,9 @@
         // the parcel as positive values.
         // Need to convert into negative values unless the value is invalid
         mCdmaDbm = in.readInt();
-        if (mCdmaDbm != Integer.MAX_VALUE) mCdmaDbm *= -1;
         mCdmaEcio = in.readInt();
-        if (mCdmaEcio != Integer.MAX_VALUE) mCdmaEcio *= -1;
         mEvdoDbm = in.readInt();
-        if (mEvdoDbm != Integer.MAX_VALUE) mEvdoDbm *= -1;
         mEvdoEcio = in.readInt();
-        if (mEvdoEcio != Integer.MAX_VALUE) mEvdoEcio *= -1;
         mEvdoSnr = in.readInt();
         if (DBG) log("CellSignalStrengthCdma(Parcel): " + toString());
     }
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index 47a7d5f..5ed5afe 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -319,11 +319,11 @@
         // BER no change;
 
         mCdmaDbm = mCdmaDbm > 0 ? -mCdmaDbm : -120;
-        mCdmaEcio = (mCdmaEcio > 0) ? -mCdmaEcio : -160;
+        mCdmaEcio = (mCdmaEcio >= 0) ? -mCdmaEcio : -160;
 
         mEvdoDbm = (mEvdoDbm > 0) ? -mEvdoDbm : -120;
-        mEvdoEcio = (mEvdoEcio >= 0) ? -mEvdoEcio : -1;
-        mEvdoSnr = ((mEvdoSnr > 0) && (mEvdoSnr <= 8)) ? mEvdoSnr : -1;
+        mEvdoEcio = (mEvdoEcio >= 0) ? -mEvdoEcio : -160;
+        mEvdoSnr = ((mEvdoSnr >= 0) && (mEvdoSnr <= 8)) ? mEvdoSnr : -1;
 
         // TS 36.214 Physical Layer Section 5.1.3, TS 36.331 RRC
         mLteSignalStrength = (mLteSignalStrength >= 0) ? mLteSignalStrength : 99;
diff --git a/tests/net/java/android/net/NetworkCapabilitiesTest.java b/tests/net/java/android/net/NetworkCapabilitiesTest.java
index ec6a5ec..c866371 100644
--- a/tests/net/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/java/android/net/NetworkCapabilitiesTest.java
@@ -17,18 +17,24 @@
 package android.net;
 
 import static android.net.NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
 import static android.net.NetworkCapabilities.RESTRICTED_CAPABILITIES;
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
 import static android.net.NetworkCapabilities.UNRESTRICTED_CAPABILITIES;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
@@ -268,6 +274,120 @@
         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
     }
 
+    @Test
+    public void testUnwantedCapabilities() {
+        NetworkCapabilities network = new NetworkCapabilities();
+
+        NetworkCapabilities request = new NetworkCapabilities();
+        assertTrue("Request: " + request + ", Network:" + network,
+                request.satisfiedByNetworkCapabilities(network));
+
+        // Adding capabilities that doesn't exist in the network anyway
+        request.addUnwantedCapability(NET_CAPABILITY_WIFI_P2P);
+        request.addUnwantedCapability(NET_CAPABILITY_NOT_METERED);
+        assertTrue(request.satisfiedByNetworkCapabilities(network));
+        assertArrayEquals(new int[] {NET_CAPABILITY_WIFI_P2P, NET_CAPABILITY_NOT_METERED},
+                request.getUnwantedCapabilities());
+
+        // This is a default capability, just want to make sure its there because we use it below.
+        assertTrue(network.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+
+        // Verify that adding unwanted capability will effectively remove it from capability list.
+        request.addUnwantedCapability(NET_CAPABILITY_NOT_RESTRICTED);
+        assertTrue(request.hasUnwantedCapability(NET_CAPABILITY_NOT_RESTRICTED));
+        assertFalse(request.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+
+
+        // Now this request won't be satisfied because network contains NOT_RESTRICTED.
+        assertFalse(request.satisfiedByNetworkCapabilities(network));
+        network.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
+        assertTrue(request.satisfiedByNetworkCapabilities(network));
+
+        // Verify that adding capability will effectively remove it from unwanted list
+        request.addCapability(NET_CAPABILITY_NOT_RESTRICTED);
+        assertTrue(request.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+        assertFalse(request.hasUnwantedCapability(NET_CAPABILITY_NOT_RESTRICTED));
+
+        assertFalse(request.satisfiedByNetworkCapabilities(network));
+        network.addCapability(NET_CAPABILITY_NOT_RESTRICTED);
+        assertTrue(request.satisfiedByNetworkCapabilities(network));
+    }
+
+    @Test
+    public void testEqualsNetCapabilities() {
+        int CAPABILITY = NET_CAPABILITY_MMS;  // An arbitrary not mutable capability.
+
+        NetworkCapabilities nc1 = new NetworkCapabilities();
+        NetworkCapabilities nc2 = new NetworkCapabilities();
+        assertTrue(nc1.equalsNetCapabilities(nc2));
+        assertEquals(nc1, nc2);
+
+        nc1.addCapability(CAPABILITY);
+        assertFalse(nc1.equalsNetCapabilities(nc2));
+        assertNotEquals(nc1, nc2);
+        nc2.addCapability(CAPABILITY);
+        assertTrue(nc1.equalsNetCapabilities(nc2));
+        assertEquals(nc1, nc2);
+
+        nc1.addUnwantedCapability(CAPABILITY);
+        assertFalse(nc1.equalsNetCapabilities(nc2));
+        nc2.addUnwantedCapability(CAPABILITY);
+        assertTrue(nc1.equalsNetCapabilities(nc2));
+
+        nc1.removeCapability(CAPABILITY);
+        assertFalse(nc1.equalsNetCapabilities(nc2));
+        nc2.removeCapability(CAPABILITY);
+        assertTrue(nc1.equalsNetCapabilities(nc2));
+    }
+
+    @Test
+    public void testCombineCapabilities() {
+        NetworkCapabilities nc1 = new NetworkCapabilities();
+        NetworkCapabilities nc2 = new NetworkCapabilities();
+
+        nc1.addUnwantedCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
+        nc1.addCapability(NET_CAPABILITY_NOT_ROAMING);
+        assertNotEquals(nc1, nc2);
+        nc2.combineCapabilities(nc1);
+        assertEquals(nc1, nc2);
+        assertTrue(nc2.hasCapability(NET_CAPABILITY_NOT_ROAMING));
+        assertTrue(nc2.hasUnwantedCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
+
+        // This will effectively move NOT_ROAMING capability from required to unwanted for nc1.
+        nc1.addUnwantedCapability(NET_CAPABILITY_NOT_ROAMING);
+
+        nc2.combineCapabilities(nc1);
+        // We will get this capability in both requested and unwanted lists thus this request
+        // will never be satisfied.
+        assertTrue(nc2.hasCapability(NET_CAPABILITY_NOT_ROAMING));
+        assertTrue(nc2.hasUnwantedCapability(NET_CAPABILITY_NOT_ROAMING));
+    }
+
+    @Test
+    public void testSetCapabilities() {
+        final int[] REQUIRED_CAPABILITIES = new int[] {
+                NET_CAPABILITY_INTERNET, NET_CAPABILITY_NOT_VPN };
+        final int[] UNWANTED_CAPABILITIES = new int[] {
+                NET_CAPABILITY_NOT_RESTRICTED, NET_CAPABILITY_NOT_METERED
+        };
+
+        NetworkCapabilities nc1 = new NetworkCapabilities();
+        NetworkCapabilities nc2 = new NetworkCapabilities();
+
+        nc1.setCapabilities(REQUIRED_CAPABILITIES, UNWANTED_CAPABILITIES);
+        assertArrayEquals(REQUIRED_CAPABILITIES, nc1.getCapabilities());
+
+        // Verify that setting and adding capabilities leads to the same object state.
+        nc2.clearAll();
+        for (int cap : REQUIRED_CAPABILITIES) {
+            nc2.addCapability(cap);
+        }
+        for (int cap : UNWANTED_CAPABILITIES) {
+            nc2.addUnwantedCapability(cap);
+        }
+        assertEquals(nc1, nc2);
+    }
+
     private void assertEqualsThroughMarshalling(NetworkCapabilities netCap) {
         Parcel p = Parcel.obtain();
         netCap.writeToParcel(p, /* flags */ 0);
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index eb3a99a..2ff92e6 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -101,6 +101,7 @@
         "io/ZipArchive.cpp",
         "link/AutoVersioner.cpp",
         "link/ManifestFixer.cpp",
+        "link/NoDefaultResourceRemover.cpp",
         "link/ProductFilter.cpp",
         "link/PrivateAttributeMover.cpp",
         "link/ReferenceLinker.cpp",
diff --git a/tools/aapt2/OWNERS b/tools/aapt2/OWNERS
index d76233e..23ec5ab 100644
--- a/tools/aapt2/OWNERS
+++ b/tools/aapt2/OWNERS
@@ -1,2 +1,2 @@
 set noparent
-adamlesinski@google.com
+toddke@google.com
diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp
index 95bf921..d0faac3 100644
--- a/tools/aapt2/ResourceTable.cpp
+++ b/tools/aapt2/ResourceTable.cpp
@@ -162,7 +162,7 @@
   const StringPiece& product;
 };
 
-bool ltConfigKeyRef(const std::unique_ptr<ResourceConfigValue>& lhs, const ConfigKey& rhs) {
+bool lt_config_key_ref(const std::unique_ptr<ResourceConfigValue>& lhs, const ConfigKey& rhs) {
   int cmp = lhs->config.compare(*rhs.config);
   if (cmp == 0) {
     cmp = StringPiece(lhs->product).compare(rhs.product);
@@ -172,8 +172,8 @@
 
 ResourceConfigValue* ResourceEntry::FindValue(const ConfigDescription& config,
                                               const StringPiece& product) {
-  auto iter =
-      std::lower_bound(values.begin(), values.end(), ConfigKey{&config, product}, ltConfigKeyRef);
+  auto iter = std::lower_bound(values.begin(), values.end(), ConfigKey{&config, product},
+                               lt_config_key_ref);
   if (iter != values.end()) {
     ResourceConfigValue* value = iter->get();
     if (value->config == config && StringPiece(value->product) == product) {
@@ -185,8 +185,8 @@
 
 ResourceConfigValue* ResourceEntry::FindOrCreateValue(const ConfigDescription& config,
                                                       const StringPiece& product) {
-  auto iter =
-      std::lower_bound(values.begin(), values.end(), ConfigKey{&config, product}, ltConfigKeyRef);
+  auto iter = std::lower_bound(values.begin(), values.end(), ConfigKey{&config, product},
+                               lt_config_key_ref);
   if (iter != values.end()) {
     ResourceConfigValue* value = iter->get();
     if (value->config == config && StringPiece(value->product) == product) {
@@ -220,15 +220,16 @@
   return results;
 }
 
-std::vector<ResourceConfigValue*> ResourceEntry::FindValuesIf(
-    const std::function<bool(ResourceConfigValue*)>& f) {
-  std::vector<ResourceConfigValue*> results;
-  for (auto& configValue : values) {
-    if (f(configValue.get())) {
-      results.push_back(configValue.get());
+bool ResourceEntry::HasDefaultValue() const {
+  const ConfigDescription& default_config = ConfigDescription::DefaultConfig();
+
+  // The default config should be at the top of the list, since the list is sorted.
+  for (auto& config_value : values) {
+    if (config_value->config == default_config) {
+      return true;
     }
   }
-  return results;
+  return false;
 }
 
 // The default handler for collisions.
diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h
index 374fe1e..8534eaa 100644
--- a/tools/aapt2/ResourceTable.h
+++ b/tools/aapt2/ResourceTable.h
@@ -104,13 +104,26 @@
   explicit ResourceEntry(const android::StringPiece& name) : name(name.to_string()) {}
 
   ResourceConfigValue* FindValue(const ConfigDescription& config);
+
   ResourceConfigValue* FindValue(const ConfigDescription& config,
                                  const android::StringPiece& product);
+
   ResourceConfigValue* FindOrCreateValue(const ConfigDescription& config,
                                          const android::StringPiece& product);
   std::vector<ResourceConfigValue*> FindAllValues(const ConfigDescription& config);
-  std::vector<ResourceConfigValue*> FindValuesIf(
-      const std::function<bool(ResourceConfigValue*)>& f);
+
+  template <typename Func>
+  std::vector<ResourceConfigValue*> FindValuesIf(Func f) {
+    std::vector<ResourceConfigValue*> results;
+    for (auto& config_value : values) {
+      if (f(config_value.get())) {
+        results.push_back(config_value.get());
+      }
+    }
+    return results;
+  }
+
+  bool HasDefaultValue() const;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ResourceEntry);
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index 12ab883..0839f6f 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -55,6 +55,7 @@
 #include "java/ProguardRules.h"
 #include "link/Linkers.h"
 #include "link/ManifestFixer.h"
+#include "link/NoDefaultResourceRemover.h"
 #include "link/ReferenceLinker.h"
 #include "link/TableMerger.h"
 #include "link/XmlCompatVersioner.h"
@@ -1785,6 +1786,14 @@
           util::make_unique<FeatureSplitSymbolTableDelegate>(context_));
     }
 
+    // Before we process anything, remove the resources whose default values don't exist.
+    // We want to force any references to these to fail the build.
+    if (!NoDefaultResourceRemover{}.Consume(context_, &final_table_)) {
+      context_->GetDiagnostics()->Error(DiagMessage()
+                                        << "failed removing resources with no defaults");
+      return 1;
+    }
+
     ReferenceLinker linker;
     if (!linker.Consume(context_, &final_table_)) {
       context_->GetDiagnostics()->Error(DiagMessage() << "failed linking references");
diff --git a/tools/aapt2/compile/InlineXmlFormatParser.cpp b/tools/aapt2/compile/InlineXmlFormatParser.cpp
index 238e339..79b0933 100644
--- a/tools/aapt2/compile/InlineXmlFormatParser.cpp
+++ b/tools/aapt2/compile/InlineXmlFormatParser.cpp
@@ -65,10 +65,6 @@
     }
 
     const ResourceName& name = ref.value().name.value();
-
-    // Use an empty string for the compilation package because we don't want to default to
-    // the local package if the user specified name="style" or something. This should just
-    // be the default namespace.
     Maybe<xml::ExtractedPackage> maybe_pkg = TransformPackageAlias(name.package);
     if (!maybe_pkg) {
       context_->GetDiagnostics()->Error(DiagMessage(src)
@@ -83,8 +79,15 @@
     InlineDeclaration decl;
     decl.el = el;
     decl.attr_name = name.entry;
-    if (!pkg.package.empty()) {
-      decl.attr_namespace_uri = xml::BuildPackageNamespace(pkg.package, private_namespace);
+
+    // We need to differentiate between no-namespace defined, or the alias resolves to an empty
+    // package, which means we must use the res-auto schema.
+    if (!name.package.empty()) {
+      if (pkg.package.empty()) {
+        decl.attr_namespace_uri = xml::kSchemaAuto;
+      } else {
+        decl.attr_namespace_uri = xml::BuildPackageNamespace(pkg.package, private_namespace);
+      }
     }
 
     inline_declarations_.push_back(std::move(decl));
diff --git a/tools/aapt2/compile/InlineXmlFormatParser_test.cpp b/tools/aapt2/compile/InlineXmlFormatParser_test.cpp
index 2b4ab96..ca4e01a 100644
--- a/tools/aapt2/compile/InlineXmlFormatParser_test.cpp
+++ b/tools/aapt2/compile/InlineXmlFormatParser_test.cpp
@@ -184,4 +184,42 @@
   // Confirm that all of the nested inline xmls are parsed out.
   ASSERT_THAT(parser.GetExtractedInlineXmlDocuments(), SizeIs(8u));
 }
+
+TEST(InlineXmlFormatParserTest, ExtractIntoAppAttribute) {
+  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
+  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(
+      <parent xmlns:app="http://schemas.android.com/apk/res-auto"
+              xmlns:aapt="http://schemas.android.com/aapt">
+            <aapt:attr name="app:foo">
+                <child />
+            </aapt:attr>
+      </parent>)");
+
+  doc->file.name = test::ParseNameOrDie("layout/main");
+
+  InlineXmlFormatParser parser;
+  ASSERT_TRUE(parser.Consume(context.get(), doc.get()));
+
+  ASSERT_THAT(doc->root, NotNull());
+  EXPECT_THAT(doc->root->FindAttribute(xml::kSchemaAuto, "foo"), NotNull());
+}
+
+TEST(InlineXmlFormatParserTest, ExtractIntoNoNamespaceAttribute) {
+  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
+  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(
+      <parent xmlns:aapt="http://schemas.android.com/aapt">
+            <aapt:attr name="foo">
+                <child />
+            </aapt:attr>
+      </parent>)");
+
+  doc->file.name = test::ParseNameOrDie("layout/main");
+
+  InlineXmlFormatParser parser;
+  ASSERT_TRUE(parser.Consume(context.get(), doc.get()));
+
+  ASSERT_THAT(doc->root, NotNull());
+  EXPECT_THAT(doc->root->FindAttribute({}, "foo"), NotNull());
+}
+
 }  // namespace aapt
diff --git a/tools/aapt2/link/NoDefaultResourceRemover.cpp b/tools/aapt2/link/NoDefaultResourceRemover.cpp
new file mode 100644
index 0000000..cfb4b26
--- /dev/null
+++ b/tools/aapt2/link/NoDefaultResourceRemover.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "link/NoDefaultResourceRemover.h"
+
+#include <algorithm>
+
+#include "ResourceTable.h"
+
+namespace aapt {
+
+static bool IsDefaultConfigRequired(const ConfigDescription& config) {
+  // We don't want to be overzealous with resource removal, so have strict requirements.
+  // If a resource defines a value for a locale-only configuration, the default configuration is
+  // required.
+  if (ConfigDescription::DefaultConfig().diff(config) == ConfigDescription::CONFIG_LOCALE) {
+    return true;
+  }
+  return false;
+}
+
+static bool KeepResource(const std::unique_ptr<ResourceEntry>& entry) {
+  if (entry->visibility.level == Visibility::Level::kPublic) {
+    // Removing a public API without the developer knowing is bad, so just leave this here for now.
+    return true;
+  }
+
+  if (entry->HasDefaultValue()) {
+    // There is a default value, no removal needed.
+    return true;
+  }
+
+  // There is no default value defined, check if removal is required.
+  for (const auto& config_value : entry->values) {
+    if (IsDefaultConfigRequired(config_value->config)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+bool NoDefaultResourceRemover::Consume(IAaptContext* context, ResourceTable* table) {
+  const ConfigDescription default_config = ConfigDescription::DefaultConfig();
+  for (auto& pkg : table->packages) {
+    for (auto& type : pkg->types) {
+      const auto end_iter = type->entries.end();
+      const auto new_end_iter =
+          std::stable_partition(type->entries.begin(), end_iter, KeepResource);
+      for (auto iter = new_end_iter; iter != end_iter; ++iter) {
+        const ResourceName name(pkg->name, type->type, (*iter)->name);
+        IDiagnostics* diag = context->GetDiagnostics();
+        diag->Warn(DiagMessage() << "removing resource " << name
+                                 << " without required default value");
+        if (context->IsVerbose()) {
+          diag->Note(DiagMessage() << "  did you forget to remove all definitions?");
+          for (const auto& config_value : (*iter)->values) {
+            if (config_value->value != nullptr) {
+              diag->Note(DiagMessage(config_value->value->GetSource()) << "defined here");
+            }
+          }
+        }
+      }
+
+      type->entries.erase(new_end_iter, type->entries.end());
+    }
+  }
+  return true;
+}
+
+}  // namespace aapt
diff --git a/tools/aapt2/link/NoDefaultResourceRemover.h b/tools/aapt2/link/NoDefaultResourceRemover.h
new file mode 100644
index 0000000..7582ef3
--- /dev/null
+++ b/tools/aapt2/link/NoDefaultResourceRemover.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAPT_LINK_NODEFAULTRESOURCEREMOVER_H
+#define AAPT_LINK_NODEFAULTRESOURCEREMOVER_H
+
+#include "android-base/macros.h"
+
+#include "process/IResourceTableConsumer.h"
+
+namespace aapt {
+
+// Removes any resource for which there exists no definition for the default configuration, where
+// for that resource type, a definition is required.
+//
+// The obvious example is when defining localized strings. If a string in the default configuration
+// has its name changed, the translations for that string won't be changed but will still cause
+// the generated R class to contain the old string name. This will cause breakages in apps that
+// still rely on the old name when the translations are updated.
+class NoDefaultResourceRemover : public IResourceTableConsumer {
+ public:
+  NoDefaultResourceRemover() = default;
+
+  bool Consume(IAaptContext* context, ResourceTable* table) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NoDefaultResourceRemover);
+};
+
+}  // namespace aapt
+
+#endif  // AAPT_LINK_NODEFAULTRESOURCEREMOVER_H
diff --git a/tools/aapt2/link/NoDefaultResourceRemover_test.cpp b/tools/aapt2/link/NoDefaultResourceRemover_test.cpp
new file mode 100644
index 0000000..943709a
--- /dev/null
+++ b/tools/aapt2/link/NoDefaultResourceRemover_test.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "link/NoDefaultResourceRemover.h"
+
+#include "test/Test.h"
+
+namespace aapt {
+
+TEST(NoDefaultResourceRemoverTest, RemoveEntryWithNoDefaultAndOnlyLocales) {
+  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
+  std::unique_ptr<ResourceTable> table =
+      test::ResourceTableBuilder()
+          .SetPackageId("android", 0x01)
+          .AddSimple("android:string/foo")
+          .AddSimple("android:string/foo", test::ParseConfigOrDie("en-rGB"))
+          .AddSimple("android:string/foo", test::ParseConfigOrDie("fr-rFR"))
+          .AddSimple("android:string/bar", test::ParseConfigOrDie("en-rGB"))
+          .AddSimple("android:string/bar", test::ParseConfigOrDie("fr-rFR"))
+          .AddSimple("android:string/bat", test::ParseConfigOrDie("en-rGB-xhdpi"))
+          .AddSimple("android:string/bat", test::ParseConfigOrDie("fr-rFR-hdpi"))
+          .AddSimple("android:string/baz", test::ParseConfigOrDie("en-rGB"))
+          .AddSimple("android:string/baz", test::ParseConfigOrDie("fr-rFR"))
+          .SetSymbolState("android:string/baz", ResourceId(0x01020002), Visibility::Level::kPublic)
+          .Build();
+
+  NoDefaultResourceRemover remover;
+  ASSERT_TRUE(remover.Consume(context.get(), table.get()));
+
+  EXPECT_TRUE(table->FindResource(test::ParseNameOrDie("android:string/foo")));
+  EXPECT_FALSE(table->FindResource(test::ParseNameOrDie("android:string/bar")));
+  EXPECT_TRUE(table->FindResource(test::ParseNameOrDie("android:string/bat")));
+  EXPECT_TRUE(table->FindResource(test::ParseNameOrDie("android:string/baz")));
+}
+
+}  // namespace aapt
diff --git a/tools/aapt2/xml/XmlDom_test.cpp b/tools/aapt2/xml/XmlDom_test.cpp
index 486b53a..ca46d53 100644
--- a/tools/aapt2/xml/XmlDom_test.cpp
+++ b/tools/aapt2/xml/XmlDom_test.cpp
@@ -154,6 +154,12 @@
       EXPECT_THAT(TransformPackageAlias("two"), Eq(make_value(ExtractedPackage{"com.two", false})));
       EXPECT_THAT(TransformPackageAlias("three"),
                   Eq(make_value(ExtractedPackage{"com.three", false})));
+    } else if (el->name == "View4") {
+      EXPECT_THAT(TransformPackageAlias("one"), Eq(make_value(ExtractedPackage{"com.one", false})));
+      EXPECT_THAT(TransformPackageAlias("two"), Eq(make_value(ExtractedPackage{"com.two", false})));
+      EXPECT_THAT(TransformPackageAlias("three"),
+                  Eq(make_value(ExtractedPackage{"com.three", false})));
+      EXPECT_THAT(TransformPackageAlias("four"), Eq(make_value(ExtractedPackage{"", true})));
     }
   }
 };
@@ -162,7 +168,9 @@
   std::unique_ptr<XmlResource> doc = test::BuildXmlDom(R"(
       <View1 xmlns:one="http://schemas.android.com/apk/res/com.one">
         <View2 xmlns:two="http://schemas.android.com/apk/res/com.two">
-          <View3 xmlns:three="http://schemas.android.com/apk/res/com.three" />
+          <View3 xmlns:three="http://schemas.android.com/apk/res/com.three">
+            <View4 xmlns:four="http://schemas.android.com/apk/res-auto" />
+          </View3>
         </View2>
       </View1>)");
 
diff --git a/tools/incident_section_gen/main.cpp b/tools/incident_section_gen/main.cpp
index 9183918..e396a63 100644
--- a/tools/incident_section_gen/main.cpp
+++ b/tools/incident_section_gen/main.cpp
@@ -203,6 +203,18 @@
             getMessageDest(field->message_type(), fieldDest);
 }
 
+// Converts Destination to a string.
+static inline string getDestString(const Destination dest) {
+    switch (dest) {
+        case DEST_AUTOMATIC: return "AUTOMATIC";
+        case DEST_LOCAL: return "LOCAL";
+        case DEST_EXPLICIT: return "EXPLICIT";
+        // UNSET is considered EXPLICIT by default.
+        case DEST_UNSET: return "EXPLICIT";
+        default: return "UNKNOWN";
+    }
+}
+
 // Get Names ===========================================================================================
 static inline string getFieldName(const FieldDescriptor* field) {
     // replace . with double underscores to avoid name conflicts since fields use snake naming convention
@@ -218,7 +230,7 @@
 
 // IsDefault ============================================================================================
 // Returns true if a field is default. Default is defined as this field has same dest as its containing message.
-// For message fields, it only looks at its field tag and own default mesaage tag, doesn't recursively go deeper.
+// For message fields, it only looks at its field tag and own default message tag, doesn't recursively go deeper.
 static inline bool isDefaultField(const FieldDescriptor* field, const Destination containerDest) {
     Destination fieldDest = getFieldDest(field);
     if (field->type() != FieldDescriptor::TYPE_MESSAGE) {
@@ -503,11 +515,12 @@
     return result;
 }
 
-static void generateCsv(Descriptor const* descriptor, const string& indent, set<string>* parents) {
+static void generateCsv(Descriptor const* descriptor, const string& indent, set<string>* parents, const Destination containerDest = DEST_UNSET) {
     DebugStringOptions options;
     options.include_comments = true;
     for (int i=0; i<descriptor->field_count(); i++) {
         const FieldDescriptor* field = descriptor->field(i);
+        const Destination fieldDest = getFieldDest(field);
         stringstream text;
         if (field->type() == FieldDescriptor::TYPE_MESSAGE) {
             text << field->message_type()->name();
@@ -515,11 +528,18 @@
             text << field->type_name();
         }
         text << " " << field->name();
+        text << " (PRIVACY=";
+        if (isDefaultField(field, containerDest)) {
+            text << getDestString(containerDest);
+        } else {
+            text << getDestString(fieldDest);
+        }
+        text << ")";
         printf("%s%s,\n", indent.c_str(), replace_string(text.str(), '\n', ' ').c_str());
         if (field->type() == FieldDescriptor::TYPE_MESSAGE &&
             parents->find(field->message_type()->full_name()) == parents->end()) {
             parents->insert(field->message_type()->full_name());
-            generateCsv(field->message_type(), indent + ",", parents);
+            generateCsv(field->message_type(), indent + ",", parents, fieldDest);
             parents->erase(field->message_type()->full_name());
         }
     }
@@ -548,7 +568,7 @@
                 || field->number() == sectionId) {
                 set<string> parents;
                 printf("%s\n", field->name().c_str());
-                generateCsv(field->message_type(), "", &parents);
+                generateCsv(field->message_type(), "", &parents, getFieldDest(field));
                 break;
             }
         }