merge in oc-release history after reset to master
diff --git a/Android.mk b/Android.mk
index 2c85d4d..9e89738 100644
--- a/Android.mk
+++ b/Android.mk
@@ -370,6 +370,7 @@
core/java/com/android/internal/statusbar/IStatusBar.aidl \
core/java/com/android/internal/statusbar/IStatusBarService.aidl \
core/java/com/android/internal/textservice/ISpellCheckerService.aidl \
+ core/java/com/android/internal/textservice/ISpellCheckerServiceCallback.aidl \
core/java/com/android/internal/textservice/ISpellCheckerSession.aidl \
core/java/com/android/internal/textservice/ISpellCheckerSessionListener.aidl \
core/java/com/android/internal/textservice/ITextServicesManager.aidl \
diff --git a/api/current.txt b/api/current.txt
index 7db661b..e2720f2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5472,11 +5472,13 @@
method public boolean canBypassDnd();
method public boolean canShowBadge();
method public int describeContents();
+ method public void enableLights(boolean);
method public void enableVibration(boolean);
method public android.media.AudioAttributes getAudioAttributes();
method public java.lang.String getGroup();
method public java.lang.String getId();
method public int getImportance();
+ method public int getLightColor();
method public int getLockscreenVisibility();
method public java.lang.CharSequence getName();
method public android.net.Uri getSound();
@@ -5484,7 +5486,7 @@
method public void setBypassDnd(boolean);
method public void setGroup(java.lang.String);
method public void setImportance(int);
- method public void setLights(boolean);
+ method public void setLightColor(int);
method public void setLockscreenVisibility(int);
method public void setShowBadge(boolean);
method public void setSound(android.net.Uri, android.media.AudioAttributes);
@@ -21990,6 +21992,7 @@
method public boolean advance();
method public long getCachedDuration();
method public android.media.DrmInitData getDrmInitData();
+ method public android.os.Bundle getMetrics();
method public java.util.Map<java.util.UUID, byte[]> getPsshInfo();
method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo);
method public int getSampleFlags();
@@ -23952,6 +23955,31 @@
field public static final java.lang.String AUTHORITY = "android.media.tv";
}
+ public static abstract interface TvContract.BaseProgramColumns implements android.media.tv.TvContract.BaseTvColumns {
+ field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
+ field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
+ field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
+ field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
+ field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
+ field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
+ field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
+ field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
+ field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
+ field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
+ field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
+ field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
+ field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
+ field public static final java.lang.String COLUMN_TITLE = "title";
+ field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
+ field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
+ field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
+ }
+
public static abstract interface TvContract.BaseTvColumns implements android.provider.BaseColumns {
field public static final java.lang.String COLUMN_PACKAGE_NAME = "package_name";
}
@@ -24034,7 +24062,7 @@
field public static final java.lang.String CONTENT_DIRECTORY = "logo";
}
- public static final class TvContract.Programs implements android.media.tv.TvContract.BaseTvColumns {
+ public static final class TvContract.Programs implements android.media.tv.TvContract.BaseProgramColumns {
field public static final java.lang.String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9";
field public static final java.lang.String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1";
field public static final java.lang.String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
@@ -24043,53 +24071,31 @@
field public static final java.lang.String AVAILABILITY_FREE_WITH_SUBSCRIPTION = "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
field public static final java.lang.String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
field public static final java.lang.String COLUMN_APP_LINK_INTENT_URI = "app_link_intent_uri";
- field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
field public static final java.lang.String COLUMN_AUTHOR = "author";
field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
- field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
- field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
- field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
- field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
field public static final deprecated java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
- field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count";
field public static final java.lang.String COLUMN_LAST_PLAYBACK_POSITION_MILLIS = "last_playback_position_millis";
field public static final java.lang.String COLUMN_LIVE = "live";
field public static final java.lang.String COLUMN_LOGO_URI = "logo_uri";
- field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price";
field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
- field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
field public static final java.lang.String COLUMN_RECORDING_PROHIBITED = "recording_prohibited";
field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date";
field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
- field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
- field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
field public static final deprecated java.lang.String COLUMN_SEASON_NUMBER = "season_number";
- field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
- field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
field public static final java.lang.String COLUMN_STARTING_PRICE = "starting_price";
field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
- field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
- field public static final java.lang.String COLUMN_TITLE = "title";
field public static final java.lang.String COLUMN_TYPE = "type";
- field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
- field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
- field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
field public static final java.lang.String COLUMN_WATCH_NEXT_TYPE = "watch_next_type";
field public static final java.lang.String COLUMN_WEIGHT = "weight";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
@@ -24145,37 +24151,15 @@
field public static final java.lang.String TRAVEL = "TRAVEL";
}
- public static final class TvContract.RecordedPrograms implements android.media.tv.TvContract.BaseTvColumns {
- field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
+ public static final class TvContract.RecordedPrograms implements android.media.tv.TvContract.BaseProgramColumns {
field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
- field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
- field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
- field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
- field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
- field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
field public static final java.lang.String COLUMN_INPUT_ID = "input_id";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
- field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
- field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
field public static final java.lang.String COLUMN_RECORDING_DATA_BYTES = "recording_data_bytes";
field public static final java.lang.String COLUMN_RECORDING_DATA_URI = "recording_data_uri";
field public static final java.lang.String COLUMN_RECORDING_DURATION_MILLIS = "recording_duration_millis";
field public static final java.lang.String COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS = "recording_expire_time_utc_millis";
- field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
- field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
- field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
- field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
- field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
- field public static final java.lang.String COLUMN_TITLE = "title";
- field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
- field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
- field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/recorded_program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/recorded_program";
field public static final android.net.Uri CONTENT_URI;
@@ -25705,7 +25689,7 @@
field public boolean isHomeProviderNetwork;
field public int networkId;
field public java.lang.String preSharedKey;
- field public int priority;
+ field public deprecated int priority;
field public java.lang.String providerFriendlyName;
field public long[] roamingConsortiumIds;
field public int status;
@@ -25810,11 +25794,14 @@
}
public static final class WifiEnterpriseConfig.Phase2 {
+ field public static final int AKA = 6; // 0x6
+ field public static final int AKA_PRIME = 7; // 0x7
field public static final int GTC = 4; // 0x4
field public static final int MSCHAP = 2; // 0x2
field public static final int MSCHAPV2 = 3; // 0x3
field public static final int NONE = 0; // 0x0
field public static final int PAP = 1; // 0x1
+ field public static final int SIM = 5; // 0x5
}
public class WifiInfo implements android.os.Parcelable {
@@ -25861,13 +25848,13 @@
method public boolean isScanAlwaysAvailable();
method public boolean isTdlsSupported();
method public boolean isWifiEnabled();
- method public boolean pingSupplicant();
+ method public deprecated boolean pingSupplicant();
method public void queryPasspointIcon(long, java.lang.String);
method public boolean reassociate();
method public boolean reconnect();
method public boolean removeNetwork(int);
method public boolean removePasspointConfiguration(java.lang.String);
- method public boolean saveConfiguration();
+ method public deprecated boolean saveConfiguration();
method public void setTdlsEnabled(java.net.InetAddress, boolean);
method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
method public boolean setWifiEnabled(boolean);
@@ -26100,7 +26087,7 @@
method public java.lang.String getSubscriptionType();
method public android.net.wifi.hotspot2.pps.UpdateParameter getSubscriptionUpdate();
method public java.util.Map<java.lang.String, byte[]> getTrustRootCertList();
- method public int getUpdateIdentififer();
+ method public int getUpdateIdentifier();
method public long getUsageLimitDataLimit();
method public long getUsageLimitStartTimeInMs();
method public long getUsageLimitTimeLimitInMinutes();
@@ -26142,7 +26129,7 @@
method public int describeContents();
method public java.security.cert.X509Certificate getCaCertificate();
method public android.net.wifi.hotspot2.pps.Credential.CertificateCredential getCertCredential();
- method public boolean getCheckAaaServerStatus();
+ method public boolean getCheckAaaServerCertStatus();
method public java.security.cert.X509Certificate[] getClientCertificateChain();
method public java.security.PrivateKey getClientPrivateKey();
method public long getCreationTimeInMs();
@@ -26223,7 +26210,7 @@
method public java.util.Map<java.lang.String, java.lang.Long> getHomeNetworkIds();
method public java.lang.String getIconUrl();
method public long[] getMatchAllOis();
- method public long[] getMatchAnysOis();
+ method public long[] getMatchAnyOis();
method public java.lang.String[] getOtherHomePartners();
method public long[] getRoamingConsortiumOis();
method public void setFqdn(java.lang.String);
@@ -26245,7 +26232,7 @@
method public int describeContents();
method public java.lang.String[] getExcludedSsidList();
method public int getMaximumBssLoadValue();
- method public long getMinHomeDownlinkBandWidht();
+ method public long getMinHomeDownlinkBandwidth();
method public long getMinHomeUplinkBandwidth();
method public long getMinRoamingDownlinkBandwidth();
method public long getMinRoamingUplinkBandwidth();
@@ -29857,6 +29844,7 @@
field public static final int BATTERY_PLUGGED_AC = 1; // 0x1
field public static final int BATTERY_PLUGGED_USB = 2; // 0x2
field public static final int BATTERY_PLUGGED_WIRELESS = 4; // 0x4
+ field public static final int BATTERY_PROPERTY_BATTERY_STATUS = 6; // 0x6
field public static final int BATTERY_PROPERTY_CAPACITY = 4; // 0x4
field public static final int BATTERY_PROPERTY_CHARGE_COUNTER = 1; // 0x1
field public static final int BATTERY_PROPERTY_CURRENT_AVERAGE = 3; // 0x3
@@ -36770,6 +36758,7 @@
method public boolean onKeyUp(int, android.view.KeyEvent);
method public void onLockscreenShown();
method public void onLowMemory();
+ method public void onPrepareShow(android.os.Bundle, int);
method public void onRequestAbortVoice(android.service.voice.VoiceInteractionSession.AbortVoiceRequest);
method public void onRequestCommand(android.service.voice.VoiceInteractionSession.CommandRequest);
method public void onRequestCompleteVoice(android.service.voice.VoiceInteractionSession.CompleteVoiceRequest);
@@ -36783,6 +36772,7 @@
method public void setDisabledShowContext(int);
method public void setKeepAwake(boolean);
method public void setTheme(int);
+ method public void setUiEnabled(boolean);
method public void show(android.os.Bundle, int);
method public void startVoiceActivity(android.content.Intent);
field public static final int SHOW_SOURCE_ACTIVITY = 16; // 0x10
@@ -44376,6 +44366,7 @@
method public android.view.ViewPropertyAnimator animate();
method public void announceForAccessibility(java.lang.CharSequence);
method public void autoFill(android.view.autofill.AutoFillValue);
+ method public void autoFillVirtual(int, android.view.autofill.AutoFillValue);
method protected boolean awakenScrollBars();
method protected boolean awakenScrollBars(int);
method protected boolean awakenScrollBars(int, boolean);
@@ -44467,7 +44458,6 @@
method public android.os.IBinder getApplicationWindowToken();
method public android.view.autofill.AutoFillType getAutoFillType();
method public android.view.autofill.AutoFillValue getAutoFillValue();
- method public android.view.autofill.VirtualViewDelegate getAutoFillVirtualViewDelegate();
method public android.graphics.drawable.Drawable getBackground();
method public android.content.res.ColorStateList getBackgroundTintList();
method public android.graphics.PorterDuff.Mode getBackgroundTintMode();
@@ -44605,6 +44595,7 @@
method public float getX();
method public float getY();
method public float getZ();
+ method public boolean hasExplicitFocusable();
method public boolean hasFocus();
method public boolean hasFocusable();
method public boolean hasNestedScrollingParent();
@@ -44765,7 +44756,7 @@
method public final void requestUnbufferedDispatch(android.view.MotionEvent);
method public static int resolveSize(int, int);
method public static int resolveSizeAndState(int, int, int);
- method public boolean restoreDefaultFocus(int);
+ method public boolean restoreDefaultFocus();
method public void restoreHierarchyState(android.util.SparseArray<android.os.Parcelable>);
method public void saveHierarchyState(android.util.SparseArray<android.os.Parcelable>);
method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
@@ -46827,7 +46818,7 @@
method public void focusChanged(android.view.View, boolean);
method public void reset();
method public void valueChanged(android.view.View);
- method public void virtualFocusChanged(android.view.View, int, android.graphics.Rect, android.view.autofill.AutoFillValue, boolean);
+ method public void virtualFocusChanged(android.view.View, int, android.graphics.Rect, boolean);
method public void virtualValueChanged(android.view.View, int, android.view.autofill.AutoFillValue);
}
@@ -46885,11 +46876,6 @@
method public android.view.autofill.FillResponse.Builder setExtras(android.os.Bundle);
}
- public abstract class VirtualViewDelegate {
- ctor public VirtualViewDelegate();
- method public abstract void autoFill(int, android.view.autofill.AutoFillValue);
- }
-
}
package android.view.inputmethod {
@@ -47300,7 +47286,7 @@
public final class TextClassificationManager {
method public java.util.List<android.view.textclassifier.TextLanguage> detectLanguages(java.lang.CharSequence);
- method public synchronized android.view.textclassifier.TextClassifier getDefaultTextClassifier();
+ method public android.view.textclassifier.TextClassifier getDefaultTextClassifier();
}
public final class TextClassificationResult {
@@ -50385,6 +50371,7 @@
method public int getAutoSizeMaxTextSize();
method public int getAutoSizeMinTextSize();
method public int getAutoSizeStepGranularity();
+ method public int[] getAutoSizeTextPresetSizes();
method public int getAutoSizeTextType();
method public int getBreakStrategy();
method public int getCompoundDrawablePadding();
@@ -50498,6 +50485,7 @@
method public void setAutoSizeMaxTextSize(int, float);
method public void setAutoSizeMinTextSize(int, float);
method public void setAutoSizeStepGranularity(int, float);
+ method public void setAutoSizeTextPresetSizes(int[]);
method public void setAutoSizeTextType(int);
method public void setBreakStrategy(int);
method public void setCompoundDrawablePadding(int);
diff --git a/api/system-current.txt b/api/system-current.txt
index 9ef0c52..14120af 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5648,11 +5648,13 @@
method public boolean canBypassDnd();
method public boolean canShowBadge();
method public int describeContents();
+ method public void enableLights(boolean);
method public void enableVibration(boolean);
method public android.media.AudioAttributes getAudioAttributes();
method public java.lang.String getGroup();
method public java.lang.String getId();
method public int getImportance();
+ method public int getLightColor();
method public int getLockscreenVisibility();
method public java.lang.CharSequence getName();
method public android.net.Uri getSound();
@@ -5665,7 +5667,7 @@
method public void setDeleted(boolean);
method public void setGroup(java.lang.String);
method public void setImportance(int);
- method public void setLights(boolean);
+ method public void setLightColor(int);
method public void setLockscreenVisibility(int);
method public void setShowBadge(boolean);
method public void setSound(android.net.Uri, android.media.AudioAttributes);
@@ -23610,6 +23612,7 @@
method public boolean advance();
method public long getCachedDuration();
method public android.media.DrmInitData getDrmInitData();
+ method public android.os.Bundle getMetrics();
method public java.util.Map<java.util.UUID, byte[]> getPsshInfo();
method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo);
method public int getSampleFlags();
@@ -25714,6 +25717,31 @@
field public static final java.lang.String AUTHORITY = "android.media.tv";
}
+ public static abstract interface TvContract.BaseProgramColumns implements android.media.tv.TvContract.BaseTvColumns {
+ field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
+ field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
+ field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
+ field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
+ field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
+ field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
+ field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
+ field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
+ field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
+ field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
+ field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
+ field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
+ field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
+ field public static final java.lang.String COLUMN_TITLE = "title";
+ field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
+ field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
+ field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
+ }
+
public static abstract interface TvContract.BaseTvColumns implements android.provider.BaseColumns {
field public static final java.lang.String COLUMN_PACKAGE_NAME = "package_name";
}
@@ -25800,7 +25828,7 @@
field public static final java.lang.String CONTENT_DIRECTORY = "logo";
}
- public static final class TvContract.Programs implements android.media.tv.TvContract.BaseTvColumns {
+ public static final class TvContract.Programs implements android.media.tv.TvContract.BaseProgramColumns {
field public static final java.lang.String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9";
field public static final java.lang.String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1";
field public static final java.lang.String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
@@ -25809,54 +25837,32 @@
field public static final java.lang.String AVAILABILITY_FREE_WITH_SUBSCRIPTION = "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
field public static final java.lang.String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
field public static final java.lang.String COLUMN_APP_LINK_INTENT_URI = "app_link_intent_uri";
- field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
field public static final java.lang.String COLUMN_AUTHOR = "author";
field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
- field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
- field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
- field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
- field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
field public static final deprecated java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
- field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count";
field public static final java.lang.String COLUMN_LAST_PLAYBACK_POSITION_MILLIS = "last_playback_position_millis";
field public static final java.lang.String COLUMN_LIVE = "live";
field public static final java.lang.String COLUMN_LOGO_URI = "logo_uri";
- field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price";
field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
- field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
field public static final java.lang.String COLUMN_RECORDING_PROHIBITED = "recording_prohibited";
field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date";
field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
- field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
- field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
field public static final deprecated java.lang.String COLUMN_SEASON_NUMBER = "season_number";
- field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
- field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
field public static final java.lang.String COLUMN_STARTING_PRICE = "starting_price";
field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
- field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
- field public static final java.lang.String COLUMN_TITLE = "title";
field public static final java.lang.String COLUMN_TRANSIENT = "transient";
field public static final java.lang.String COLUMN_TYPE = "type";
- field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
- field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
- field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
field public static final java.lang.String COLUMN_WATCH_NEXT_TYPE = "watch_next_type";
field public static final java.lang.String COLUMN_WEIGHT = "weight";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
@@ -25912,37 +25918,15 @@
field public static final java.lang.String TRAVEL = "TRAVEL";
}
- public static final class TvContract.RecordedPrograms implements android.media.tv.TvContract.BaseTvColumns {
- field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
+ public static final class TvContract.RecordedPrograms implements android.media.tv.TvContract.BaseProgramColumns {
field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
- field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
- field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
- field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
- field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
- field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
field public static final java.lang.String COLUMN_INPUT_ID = "input_id";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
- field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
- field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
field public static final java.lang.String COLUMN_RECORDING_DATA_BYTES = "recording_data_bytes";
field public static final java.lang.String COLUMN_RECORDING_DATA_URI = "recording_data_uri";
field public static final java.lang.String COLUMN_RECORDING_DURATION_MILLIS = "recording_duration_millis";
field public static final java.lang.String COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS = "recording_expire_time_utc_millis";
- field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
- field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
- field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
- field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
- field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
- field public static final java.lang.String COLUMN_TITLE = "title";
- field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
- field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
- field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/recorded_program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/recorded_program";
field public static final android.net.Uri CONTENT_URI;
@@ -28218,7 +28202,7 @@
field public int numScorerOverride;
field public int numScorerOverrideAndSwitchedNetwork;
field public java.lang.String preSharedKey;
- field public int priority;
+ field public deprecated int priority;
field public java.lang.String providerFriendlyName;
field public long[] roamingConsortiumIds;
field public int status;
@@ -28340,11 +28324,14 @@
}
public static final class WifiEnterpriseConfig.Phase2 {
+ field public static final int AKA = 6; // 0x6
+ field public static final int AKA_PRIME = 7; // 0x7
field public static final int GTC = 4; // 0x4
field public static final int MSCHAP = 2; // 0x2
field public static final int MSCHAPV2 = 3; // 0x3
field public static final int NONE = 0; // 0x0
field public static final int PAP = 1; // 0x1
+ field public static final int SIM = 5; // 0x5
}
public class WifiInfo implements android.os.Parcelable {
@@ -28402,13 +28389,13 @@
method public boolean isWifiApEnabled();
method public boolean isWifiEnabled();
method public boolean isWifiScannerSupported();
- method public boolean pingSupplicant();
+ method public deprecated boolean pingSupplicant();
method public void queryPasspointIcon(long, java.lang.String);
method public boolean reassociate();
method public boolean reconnect();
method public boolean removeNetwork(int);
method public boolean removePasspointConfiguration(java.lang.String);
- method public boolean saveConfiguration();
+ method public deprecated boolean saveConfiguration();
method public void setTdlsEnabled(java.net.InetAddress, boolean);
method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
method public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration);
@@ -28810,7 +28797,7 @@
method public java.lang.String getSubscriptionType();
method public android.net.wifi.hotspot2.pps.UpdateParameter getSubscriptionUpdate();
method public java.util.Map<java.lang.String, byte[]> getTrustRootCertList();
- method public int getUpdateIdentififer();
+ method public int getUpdateIdentifier();
method public long getUsageLimitDataLimit();
method public long getUsageLimitStartTimeInMs();
method public long getUsageLimitTimeLimitInMinutes();
@@ -28852,7 +28839,7 @@
method public int describeContents();
method public java.security.cert.X509Certificate getCaCertificate();
method public android.net.wifi.hotspot2.pps.Credential.CertificateCredential getCertCredential();
- method public boolean getCheckAaaServerStatus();
+ method public boolean getCheckAaaServerCertStatus();
method public java.security.cert.X509Certificate[] getClientCertificateChain();
method public java.security.PrivateKey getClientPrivateKey();
method public long getCreationTimeInMs();
@@ -28933,7 +28920,7 @@
method public java.util.Map<java.lang.String, java.lang.Long> getHomeNetworkIds();
method public java.lang.String getIconUrl();
method public long[] getMatchAllOis();
- method public long[] getMatchAnysOis();
+ method public long[] getMatchAnyOis();
method public java.lang.String[] getOtherHomePartners();
method public long[] getRoamingConsortiumOis();
method public void setFqdn(java.lang.String);
@@ -28955,7 +28942,7 @@
method public int describeContents();
method public java.lang.String[] getExcludedSsidList();
method public int getMaximumBssLoadValue();
- method public long getMinHomeDownlinkBandWidht();
+ method public long getMinHomeDownlinkBandwidth();
method public long getMinHomeUplinkBandwidth();
method public long getMinRoamingDownlinkBandwidth();
method public long getMinRoamingUplinkBandwidth();
@@ -32580,6 +32567,7 @@
field public static final int BATTERY_PLUGGED_AC = 1; // 0x1
field public static final int BATTERY_PLUGGED_USB = 2; // 0x2
field public static final int BATTERY_PLUGGED_WIRELESS = 4; // 0x4
+ field public static final int BATTERY_PROPERTY_BATTERY_STATUS = 6; // 0x6
field public static final int BATTERY_PROPERTY_CAPACITY = 4; // 0x4
field public static final int BATTERY_PROPERTY_CHARGE_COUNTER = 1; // 0x1
field public static final int BATTERY_PROPERTY_CURRENT_AVERAGE = 3; // 0x3
@@ -39868,6 +39856,7 @@
method public boolean onKeyUp(int, android.view.KeyEvent);
method public void onLockscreenShown();
method public void onLowMemory();
+ method public void onPrepareShow(android.os.Bundle, int);
method public void onRequestAbortVoice(android.service.voice.VoiceInteractionSession.AbortVoiceRequest);
method public void onRequestCommand(android.service.voice.VoiceInteractionSession.CommandRequest);
method public void onRequestCompleteVoice(android.service.voice.VoiceInteractionSession.CompleteVoiceRequest);
@@ -39881,6 +39870,7 @@
method public void setDisabledShowContext(int);
method public void setKeepAwake(boolean);
method public void setTheme(int);
+ method public void setUiEnabled(boolean);
method public void show(android.os.Bundle, int);
method public void startVoiceActivity(android.content.Intent);
field public static final int SHOW_SOURCE_ACTIVITY = 16; // 0x10
@@ -47792,6 +47782,7 @@
method public android.view.ViewPropertyAnimator animate();
method public void announceForAccessibility(java.lang.CharSequence);
method public void autoFill(android.view.autofill.AutoFillValue);
+ method public void autoFillVirtual(int, android.view.autofill.AutoFillValue);
method protected boolean awakenScrollBars();
method protected boolean awakenScrollBars(int);
method protected boolean awakenScrollBars(int, boolean);
@@ -47883,7 +47874,6 @@
method public android.os.IBinder getApplicationWindowToken();
method public android.view.autofill.AutoFillType getAutoFillType();
method public android.view.autofill.AutoFillValue getAutoFillValue();
- method public android.view.autofill.VirtualViewDelegate getAutoFillVirtualViewDelegate();
method public android.graphics.drawable.Drawable getBackground();
method public android.content.res.ColorStateList getBackgroundTintList();
method public android.graphics.PorterDuff.Mode getBackgroundTintMode();
@@ -48021,6 +48011,7 @@
method public float getX();
method public float getY();
method public float getZ();
+ method public boolean hasExplicitFocusable();
method public boolean hasFocus();
method public boolean hasFocusable();
method public boolean hasNestedScrollingParent();
@@ -48181,7 +48172,7 @@
method public final void requestUnbufferedDispatch(android.view.MotionEvent);
method public static int resolveSize(int, int);
method public static int resolveSizeAndState(int, int, int);
- method public boolean restoreDefaultFocus(int);
+ method public boolean restoreDefaultFocus();
method public void restoreHierarchyState(android.util.SparseArray<android.os.Parcelable>);
method public void saveHierarchyState(android.util.SparseArray<android.os.Parcelable>);
method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
@@ -50246,7 +50237,7 @@
method public void focusChanged(android.view.View, boolean);
method public void reset();
method public void valueChanged(android.view.View);
- method public void virtualFocusChanged(android.view.View, int, android.graphics.Rect, android.view.autofill.AutoFillValue, boolean);
+ method public void virtualFocusChanged(android.view.View, int, android.graphics.Rect, boolean);
method public void virtualValueChanged(android.view.View, int, android.view.autofill.AutoFillValue);
}
@@ -50304,11 +50295,6 @@
method public android.view.autofill.FillResponse.Builder setExtras(android.os.Bundle);
}
- public abstract class VirtualViewDelegate {
- ctor public VirtualViewDelegate();
- method public abstract void autoFill(int, android.view.autofill.AutoFillValue);
- }
-
}
package android.view.inputmethod {
@@ -50719,7 +50705,7 @@
public final class TextClassificationManager {
method public java.util.List<android.view.textclassifier.TextLanguage> detectLanguages(java.lang.CharSequence);
- method public synchronized android.view.textclassifier.TextClassifier getDefaultTextClassifier();
+ method public android.view.textclassifier.TextClassifier getDefaultTextClassifier();
}
public final class TextClassificationResult {
@@ -54165,6 +54151,7 @@
method public int getAutoSizeMaxTextSize();
method public int getAutoSizeMinTextSize();
method public int getAutoSizeStepGranularity();
+ method public int[] getAutoSizeTextPresetSizes();
method public int getAutoSizeTextType();
method public int getBreakStrategy();
method public int getCompoundDrawablePadding();
@@ -54278,6 +54265,7 @@
method public void setAutoSizeMaxTextSize(int, float);
method public void setAutoSizeMinTextSize(int, float);
method public void setAutoSizeStepGranularity(int, float);
+ method public void setAutoSizeTextPresetSizes(int[]);
method public void setAutoSizeTextType(int);
method public void setBreakStrategy(int);
method public void setCompoundDrawablePadding(int);
diff --git a/api/test-current.txt b/api/test-current.txt
index 37da0d3..4fb669a 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -5482,11 +5482,13 @@
method public boolean canBypassDnd();
method public boolean canShowBadge();
method public int describeContents();
+ method public void enableLights(boolean);
method public void enableVibration(boolean);
method public android.media.AudioAttributes getAudioAttributes();
method public java.lang.String getGroup();
method public java.lang.String getId();
method public int getImportance();
+ method public int getLightColor();
method public int getLockscreenVisibility();
method public java.lang.CharSequence getName();
method public android.net.Uri getSound();
@@ -5494,7 +5496,7 @@
method public void setBypassDnd(boolean);
method public void setGroup(java.lang.String);
method public void setImportance(int);
- method public void setLights(boolean);
+ method public void setLightColor(int);
method public void setLockscreenVisibility(int);
method public void setShowBadge(boolean);
method public void setSound(android.net.Uri, android.media.AudioAttributes);
@@ -22082,6 +22084,7 @@
method public boolean advance();
method public long getCachedDuration();
method public android.media.DrmInitData getDrmInitData();
+ method public android.os.Bundle getMetrics();
method public java.util.Map<java.util.UUID, byte[]> getPsshInfo();
method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo);
method public int getSampleFlags();
@@ -24044,6 +24047,31 @@
field public static final java.lang.String AUTHORITY = "android.media.tv";
}
+ public static abstract interface TvContract.BaseProgramColumns implements android.media.tv.TvContract.BaseTvColumns {
+ field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
+ field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
+ field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
+ field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
+ field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
+ field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
+ field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
+ field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
+ field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
+ field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
+ field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
+ field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
+ field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
+ field public static final java.lang.String COLUMN_TITLE = "title";
+ field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
+ field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
+ field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
+ }
+
public static abstract interface TvContract.BaseTvColumns implements android.provider.BaseColumns {
field public static final java.lang.String COLUMN_PACKAGE_NAME = "package_name";
}
@@ -24126,7 +24154,7 @@
field public static final java.lang.String CONTENT_DIRECTORY = "logo";
}
- public static final class TvContract.Programs implements android.media.tv.TvContract.BaseTvColumns {
+ public static final class TvContract.Programs implements android.media.tv.TvContract.BaseProgramColumns {
field public static final java.lang.String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9";
field public static final java.lang.String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1";
field public static final java.lang.String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
@@ -24135,53 +24163,31 @@
field public static final java.lang.String AVAILABILITY_FREE_WITH_SUBSCRIPTION = "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
field public static final java.lang.String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
field public static final java.lang.String COLUMN_APP_LINK_INTENT_URI = "app_link_intent_uri";
- field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
field public static final java.lang.String COLUMN_AUTHOR = "author";
field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
- field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
- field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
- field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
- field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
field public static final deprecated java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
- field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count";
field public static final java.lang.String COLUMN_LAST_PLAYBACK_POSITION_MILLIS = "last_playback_position_millis";
field public static final java.lang.String COLUMN_LIVE = "live";
field public static final java.lang.String COLUMN_LOGO_URI = "logo_uri";
- field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price";
field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
- field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
field public static final java.lang.String COLUMN_RECORDING_PROHIBITED = "recording_prohibited";
field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date";
field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
- field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
- field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
field public static final deprecated java.lang.String COLUMN_SEASON_NUMBER = "season_number";
- field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
- field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
field public static final java.lang.String COLUMN_STARTING_PRICE = "starting_price";
field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
- field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
- field public static final java.lang.String COLUMN_TITLE = "title";
field public static final java.lang.String COLUMN_TYPE = "type";
- field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
- field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
- field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
field public static final java.lang.String COLUMN_WATCH_NEXT_TYPE = "watch_next_type";
field public static final java.lang.String COLUMN_WEIGHT = "weight";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
@@ -24237,37 +24243,15 @@
field public static final java.lang.String TRAVEL = "TRAVEL";
}
- public static final class TvContract.RecordedPrograms implements android.media.tv.TvContract.BaseTvColumns {
- field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
+ public static final class TvContract.RecordedPrograms implements android.media.tv.TvContract.BaseProgramColumns {
field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
- field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
- field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
- field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
- field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
- field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
field public static final java.lang.String COLUMN_INPUT_ID = "input_id";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
- field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
- field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
- field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
field public static final java.lang.String COLUMN_RECORDING_DATA_BYTES = "recording_data_bytes";
field public static final java.lang.String COLUMN_RECORDING_DATA_URI = "recording_data_uri";
field public static final java.lang.String COLUMN_RECORDING_DURATION_MILLIS = "recording_duration_millis";
field public static final java.lang.String COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS = "recording_expire_time_utc_millis";
- field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
- field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
- field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
- field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
- field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
- field public static final java.lang.String COLUMN_TITLE = "title";
- field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
- field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
- field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/recorded_program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/recorded_program";
field public static final android.net.Uri CONTENT_URI;
@@ -25797,7 +25781,7 @@
field public boolean isHomeProviderNetwork;
field public int networkId;
field public java.lang.String preSharedKey;
- field public int priority;
+ field public deprecated int priority;
field public java.lang.String providerFriendlyName;
field public long[] roamingConsortiumIds;
field public int status;
@@ -25902,11 +25886,14 @@
}
public static final class WifiEnterpriseConfig.Phase2 {
+ field public static final int AKA = 6; // 0x6
+ field public static final int AKA_PRIME = 7; // 0x7
field public static final int GTC = 4; // 0x4
field public static final int MSCHAP = 2; // 0x2
field public static final int MSCHAPV2 = 3; // 0x3
field public static final int NONE = 0; // 0x0
field public static final int PAP = 1; // 0x1
+ field public static final int SIM = 5; // 0x5
}
public class WifiInfo implements android.os.Parcelable {
@@ -25953,13 +25940,13 @@
method public boolean isScanAlwaysAvailable();
method public boolean isTdlsSupported();
method public boolean isWifiEnabled();
- method public boolean pingSupplicant();
+ method public deprecated boolean pingSupplicant();
method public void queryPasspointIcon(long, java.lang.String);
method public boolean reassociate();
method public boolean reconnect();
method public boolean removeNetwork(int);
method public boolean removePasspointConfiguration(java.lang.String);
- method public boolean saveConfiguration();
+ method public deprecated boolean saveConfiguration();
method public void setTdlsEnabled(java.net.InetAddress, boolean);
method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
method public boolean setWifiEnabled(boolean);
@@ -26192,7 +26179,7 @@
method public java.lang.String getSubscriptionType();
method public android.net.wifi.hotspot2.pps.UpdateParameter getSubscriptionUpdate();
method public java.util.Map<java.lang.String, byte[]> getTrustRootCertList();
- method public int getUpdateIdentififer();
+ method public int getUpdateIdentifier();
method public long getUsageLimitDataLimit();
method public long getUsageLimitStartTimeInMs();
method public long getUsageLimitTimeLimitInMinutes();
@@ -26234,7 +26221,7 @@
method public int describeContents();
method public java.security.cert.X509Certificate getCaCertificate();
method public android.net.wifi.hotspot2.pps.Credential.CertificateCredential getCertCredential();
- method public boolean getCheckAaaServerStatus();
+ method public boolean getCheckAaaServerCertStatus();
method public java.security.cert.X509Certificate[] getClientCertificateChain();
method public java.security.PrivateKey getClientPrivateKey();
method public long getCreationTimeInMs();
@@ -26315,7 +26302,7 @@
method public java.util.Map<java.lang.String, java.lang.Long> getHomeNetworkIds();
method public java.lang.String getIconUrl();
method public long[] getMatchAllOis();
- method public long[] getMatchAnysOis();
+ method public long[] getMatchAnyOis();
method public java.lang.String[] getOtherHomePartners();
method public long[] getRoamingConsortiumOis();
method public void setFqdn(java.lang.String);
@@ -26337,7 +26324,7 @@
method public int describeContents();
method public java.lang.String[] getExcludedSsidList();
method public int getMaximumBssLoadValue();
- method public long getMinHomeDownlinkBandWidht();
+ method public long getMinHomeDownlinkBandwidth();
method public long getMinHomeUplinkBandwidth();
method public long getMinRoamingDownlinkBandwidth();
method public long getMinRoamingUplinkBandwidth();
@@ -29949,6 +29936,7 @@
field public static final int BATTERY_PLUGGED_AC = 1; // 0x1
field public static final int BATTERY_PLUGGED_USB = 2; // 0x2
field public static final int BATTERY_PLUGGED_WIRELESS = 4; // 0x4
+ field public static final int BATTERY_PROPERTY_BATTERY_STATUS = 6; // 0x6
field public static final int BATTERY_PROPERTY_CAPACITY = 4; // 0x4
field public static final int BATTERY_PROPERTY_CHARGE_COUNTER = 1; // 0x1
field public static final int BATTERY_PROPERTY_CURRENT_AVERAGE = 3; // 0x3
@@ -36905,6 +36893,7 @@
method public boolean onKeyUp(int, android.view.KeyEvent);
method public void onLockscreenShown();
method public void onLowMemory();
+ method public void onPrepareShow(android.os.Bundle, int);
method public void onRequestAbortVoice(android.service.voice.VoiceInteractionSession.AbortVoiceRequest);
method public void onRequestCommand(android.service.voice.VoiceInteractionSession.CommandRequest);
method public void onRequestCompleteVoice(android.service.voice.VoiceInteractionSession.CompleteVoiceRequest);
@@ -36918,6 +36907,7 @@
method public void setDisabledShowContext(int);
method public void setKeepAwake(boolean);
method public void setTheme(int);
+ method public void setUiEnabled(boolean);
method public void show(android.os.Bundle, int);
method public void startVoiceActivity(android.content.Intent);
field public static final int SHOW_SOURCE_ACTIVITY = 16; // 0x10
@@ -44682,6 +44672,7 @@
method public android.view.ViewPropertyAnimator animate();
method public void announceForAccessibility(java.lang.CharSequence);
method public void autoFill(android.view.autofill.AutoFillValue);
+ method public void autoFillVirtual(int, android.view.autofill.AutoFillValue);
method protected boolean awakenScrollBars();
method protected boolean awakenScrollBars(int);
method protected boolean awakenScrollBars(int, boolean);
@@ -44773,7 +44764,6 @@
method public android.os.IBinder getApplicationWindowToken();
method public android.view.autofill.AutoFillType getAutoFillType();
method public android.view.autofill.AutoFillValue getAutoFillValue();
- method public android.view.autofill.VirtualViewDelegate getAutoFillVirtualViewDelegate();
method public android.graphics.drawable.Drawable getBackground();
method public android.content.res.ColorStateList getBackgroundTintList();
method public android.graphics.PorterDuff.Mode getBackgroundTintMode();
@@ -44912,6 +44902,7 @@
method public float getX();
method public float getY();
method public float getZ();
+ method public boolean hasExplicitFocusable();
method public boolean hasFocus();
method public boolean hasFocusable();
method public boolean hasNestedScrollingParent();
@@ -45072,7 +45063,7 @@
method public final void requestUnbufferedDispatch(android.view.MotionEvent);
method public static int resolveSize(int, int);
method public static int resolveSizeAndState(int, int, int);
- method public boolean restoreDefaultFocus(int);
+ method public boolean restoreDefaultFocus();
method public void restoreHierarchyState(android.util.SparseArray<android.os.Parcelable>);
method public void saveHierarchyState(android.util.SparseArray<android.os.Parcelable>);
method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
@@ -47140,7 +47131,7 @@
method public void focusChanged(android.view.View, boolean);
method public void reset();
method public void valueChanged(android.view.View);
- method public void virtualFocusChanged(android.view.View, int, android.graphics.Rect, android.view.autofill.AutoFillValue, boolean);
+ method public void virtualFocusChanged(android.view.View, int, android.graphics.Rect, boolean);
method public void virtualValueChanged(android.view.View, int, android.view.autofill.AutoFillValue);
}
@@ -47198,11 +47189,6 @@
method public android.view.autofill.FillResponse.Builder setExtras(android.os.Bundle);
}
- public abstract class VirtualViewDelegate {
- ctor public VirtualViewDelegate();
- method public abstract void autoFill(int, android.view.autofill.AutoFillValue);
- }
-
}
package android.view.inputmethod {
@@ -47613,7 +47599,7 @@
public final class TextClassificationManager {
method public java.util.List<android.view.textclassifier.TextLanguage> detectLanguages(java.lang.CharSequence);
- method public synchronized android.view.textclassifier.TextClassifier getDefaultTextClassifier();
+ method public android.view.textclassifier.TextClassifier getDefaultTextClassifier();
}
public final class TextClassificationResult {
@@ -50705,6 +50691,7 @@
method public int getAutoSizeMaxTextSize();
method public int getAutoSizeMinTextSize();
method public int getAutoSizeStepGranularity();
+ method public int[] getAutoSizeTextPresetSizes();
method public int getAutoSizeTextType();
method public int getBreakStrategy();
method public int getCompoundDrawablePadding();
@@ -50818,6 +50805,7 @@
method public void setAutoSizeMaxTextSize(int, float);
method public void setAutoSizeMinTextSize(int, float);
method public void setAutoSizeStepGranularity(int, float);
+ method public void setAutoSizeTextPresetSizes(int[]);
method public void setAutoSizeTextType(int);
method public void setBreakStrategy(int);
method public void setCompoundDrawablePadding(int);
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 7901737..a6d2986 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -352,7 +352,7 @@
bool BootAnimation::android()
{
- ALOGD("BootAnimationShownTiming: BootAnimation start time: %" PRId64 "ms", elapsedRealtime());
+ ALOGD("BootAnimationShownTiming start time: %" PRId64 "ms", elapsedRealtime());
initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");
initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png");
@@ -878,7 +878,7 @@
const int animationX = (mWidth - animation.width) / 2;
const int animationY = (mHeight - animation.height) / 2;
- ALOGD("BootAnimationShownTiming: BootAnimation start time: %" PRId64 "ms", elapsedRealtime());
+ ALOGD("BootAnimationShownTiming start time: %" PRId64 "ms", elapsedRealtime());
for (size_t i=0 ; i<pcount ; i++) {
const Animation::Part& part(animation.parts[i]);
const size_t fcount = part.frames.size();
diff --git a/cmds/telecom/src/com/android/commands/telecom/Telecom.java b/cmds/telecom/src/com/android/commands/telecom/Telecom.java
index 63f6c92..8e9b91d 100644
--- a/cmds/telecom/src/com/android/commands/telecom/Telecom.java
+++ b/cmds/telecom/src/com/android/commands/telecom/Telecom.java
@@ -20,7 +20,6 @@
import android.content.Context;
import android.net.Uri;
import android.os.IUserManager;
-import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
@@ -51,6 +50,7 @@
private static final String COMMAND_SET_DEFAULT_DIALER = "set-default-dialer";
private static final String COMMAND_GET_DEFAULT_DIALER = "get-default-dialer";
private static final String COMMAND_GET_SYSTEM_DIALER = "get-system-dialer";
+ private static final String COMMAND_WAIT_ON_HANDLERS = "wait-on-handlers";
private ComponentName mComponent;
private String mAccountId;
@@ -69,6 +69,7 @@
"usage: telecom set-default-dialer <PACKAGE>\n" +
"usage: telecom get-default-dialer\n" +
"usage: telecom get-system-dialer\n" +
+ "usage: telecom wait-on-handlers\n" +
"\n" +
"telecom set-phone-account-enabled: Enables the given phone account, if it has \n" +
" already been registered with Telecom.\n" +
@@ -80,7 +81,9 @@
"\n" +
"telecom get-default-dialer: Displays the current default dialer. \n" +
"\n" +
- "telecom get-system-dialer: Displays the current system dialer. \n"
+ "telecom get-system-dialer: Displays the current system dialer. \n" +
+ "\n" +
+ "telecom wait-on-handlers: Wait until all handlers finish their work. \n"
);
}
@@ -125,6 +128,9 @@
case COMMAND_GET_SYSTEM_DIALER:
runGetSystemDialer();
break;
+ case COMMAND_WAIT_ON_HANDLERS:
+ runWaitOnHandler();
+ break;
default:
throw new IllegalArgumentException ("unknown command '" + command + "'");
}
@@ -192,6 +198,10 @@
System.out.println(mTelecomService.getSystemDialerPackage());
}
+ private void runWaitOnHandler() throws RemoteException {
+
+ }
+
private PhoneAccountHandle getPhoneAccountHandleFromArgs() throws RemoteException{
final ComponentName component = parseComponentName(nextArgRequired());
final String accountId = nextArgRequired();
diff --git a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/InteractionController.java b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/InteractionController.java
index 73e46f1..28a5646 100644
--- a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/InteractionController.java
+++ b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/InteractionController.java
@@ -32,8 +32,6 @@
import android.view.MotionEvent.PointerProperties;
import android.view.accessibility.AccessibilityEvent;
-import com.android.internal.util.Predicate;
-
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeoutException;
@@ -261,7 +259,7 @@
}
/**
- * Returns a Runnable for use in {@link #runAndWaitForEvents(Runnable, Predicate, long) to
+ * Returns a Runnable for use in {@link #runAndWaitForEvents(Runnable, AccessibilityEventFilter, long) to
* perform a click.
*
* @param x coordinate
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 66b2355..c88448a 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -813,8 +813,11 @@
/**
* Reverses the execution of the operations within this transaction. The Fragment states will
* only be modified if optimizations are not allowed.
+ *
+ * @param moveToState {@code true} if added fragments should be moved to their final state
+ * in unoptimized transactions
*/
- void executePopOps() {
+ void executePopOps(boolean moveToState) {
for (int opNum = mOps.size() - 1; opNum >= 0; opNum--) {
final Op op = mOps.get(opNum);
Fragment f = op.fragment;
@@ -860,7 +863,7 @@
mManager.moveFragmentToExpectedState(f);
}
}
- if (!mAllowOptimization) {
+ if (!mAllowOptimization && moveToState) {
mManager.moveToState(mManager.mCurState, true);
}
}
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index b7c0737..d32cf3c 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -2170,7 +2170,7 @@
if (isPop) {
record.executeOps();
} else {
- record.executePopOps();
+ record.executePopOps(false);
}
// move to the end
@@ -2280,7 +2280,10 @@
final boolean isPop = isRecordPop.get(i);
if (isPop) {
record.bumpBackStackNesting(-1);
- record.executePopOps();
+ // Only execute the add operations at the end of
+ // all transactions.
+ boolean moveToState = i == (endIndex - 1);
+ record.executePopOps(moveToState);
} else {
record.bumpBackStackNesting(1);
record.executeOps();
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 58cd310..cc6f6e1 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -40,7 +40,7 @@
{
void cancelAllNotifications(String pkg, int userId);
- void clearData(String pkg, int uid);
+ void clearData(String pkg, int uid, boolean fromApp);
void enqueueToast(String pkg, ITransientNotification callback, int duration);
void cancelToast(String pkg, ITransientNotification callback);
void enqueueNotificationWithTag(String pkg, String opPkg, String tag, int id,
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 44e328e..9ef40b4 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -49,7 +49,6 @@
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
-import android.service.notification.StatusBarNotification;
import android.text.BidiFormatter;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
@@ -3128,7 +3127,7 @@
* Not all devices will honor all (or even any) of these values.
*
- * @deprecated use {@link NotificationChannel#setLights(boolean)} instead.
+ * @deprecated use {@link NotificationChannel#enableLights(boolean)} instead.
* @see Notification#ledARGB
* @see Notification#ledOnMS
* @see Notification#ledOffMS
@@ -3227,7 +3226,7 @@
* For all default values, use {@link #DEFAULT_ALL}.
*
* @deprecated use {@link NotificationChannel#enableVibration(boolean)} and
- * {@link NotificationChannel#setLights(boolean)} and
+ * {@link NotificationChannel#enableLights(boolean)} and
* {@link NotificationChannel#setSound(Uri, AudioAttributes)} instead.
*/
@Deprecated
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index afcbcdf..1a51608 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -21,7 +21,7 @@
import org.xmlpull.v1.XmlSerializer;
import android.annotation.SystemApi;
-import android.app.NotificationManager;
+import android.graphics.Color;
import android.media.AudioAttributes;
import android.net.Uri;
import android.os.Parcel;
@@ -51,7 +51,6 @@
private static final String ATT_VISIBILITY = "visibility";
private static final String ATT_IMPORTANCE = "importance";
private static final String ATT_LIGHTS = "lights";
- //TODO: add support for light colors
private static final String ATT_LIGHT_COLOR = "light_color";
private static final String ATT_VIBRATION = "vibration";
private static final String ATT_VIBRATION_ENABLED = "vibration_enabled";
@@ -129,7 +128,7 @@
USER_LOCKED_AUDIO_ATTRIBUTES
};
-
+ private static final int DEFAULT_LIGHT_COLOR = 0;
private static final int DEFAULT_VISIBILITY =
NotificationManager.VISIBILITY_NO_OVERRIDE;
private static final int DEFAULT_IMPORTANCE =
@@ -144,6 +143,7 @@
private int mLockscreenVisibility = DEFAULT_VISIBILITY;
private Uri mSound;
private boolean mLights;
+ private int mLightColor = DEFAULT_LIGHT_COLOR;
private long[] mVibration;
private int mUserLockedFields;
private boolean mVibrationEnabled;
@@ -194,6 +194,7 @@
mGroup = null;
}
mAudioAttributes = in.readInt() > 0 ? AudioAttributes.CREATOR.createFromParcel(in) : null;
+ mLightColor = in.readInt();
}
@Override
@@ -232,6 +233,7 @@
} else {
dest.writeInt(0);
}
+ dest.writeInt(mLightColor);
}
/**
@@ -331,11 +333,22 @@
* Only modifiable before the channel is submitted to
* {@link NotificationManager#notify(String, int, Notification)}.
*/
- public void setLights(boolean lights) {
+ public void enableLights(boolean lights) {
this.mLights = lights;
}
/**
+ * Sets the notification light color for notifications posted to this channel, if lights are
+ * {@link #enableLights(boolean) enabled} on this channel and the device supports that feature.
+ *
+ * Only modifiable before the channel is submitted to
+ * {@link NotificationManager#notify(String, int, Notification)}.
+ */
+ public void setLightColor(int argb) {
+ this.mLightColor = argb;
+ }
+
+ /**
* Sets whether notification posted to this channel should vibrate. The vibration pattern can
* be set with {@link #setVibrationPattern(long[])}.
*
@@ -411,6 +424,14 @@
}
/**
+ * Returns the notification light color for notifications posted to this channel. Irrelevant
+ * unless {@link #shouldShowLights()}.
+ */
+ public int getLightColor() {
+ return mLightColor;
+ }
+
+ /**
* Returns whether notifications posted to this channel always vibrate.
*/
public boolean shouldVibrate() {
@@ -478,7 +499,8 @@
!= safeInt(parser, ATT_PRIORITY, Notification.PRIORITY_DEFAULT));
setLockscreenVisibility(safeInt(parser, ATT_VISIBILITY, DEFAULT_VISIBILITY));
setSound(safeUri(parser, ATT_SOUND), safeAudioAttributes(parser));
- setLights(safeBool(parser, ATT_LIGHTS, false));
+ enableLights(safeBool(parser, ATT_LIGHTS, false));
+ setLightColor(safeInt(parser, ATT_LIGHT_COLOR, DEFAULT_LIGHT_COLOR));
enableVibration(safeBool(parser, ATT_VIBRATION_ENABLED, false));
setVibrationPattern(safeLongArray(parser, ATT_VIBRATION, null));
setShowBadge(safeBool(parser, ATT_SHOW_BADGE, false));
@@ -519,6 +541,9 @@
if (shouldShowLights()) {
out.attribute(null, ATT_LIGHTS, Boolean.toString(shouldShowLights()));
}
+ if (getLightColor() != DEFAULT_LIGHT_COLOR) {
+ out.attribute(null, ATT_LIGHT_COLOR, Integer.toString(getLightColor()));
+ }
if (shouldVibrate()) {
out.attribute(null, ATT_VIBRATION_ENABLED, Boolean.toString(shouldVibrate()));
}
@@ -569,6 +594,7 @@
record.put(ATT_FLAGS, Integer.toString(getAudioAttributes().getFlags()));
}
record.put(ATT_LIGHTS, Boolean.toString(shouldShowLights()));
+ record.put(ATT_LIGHT_COLOR, Integer.toString(getLightColor()));
record.put(ATT_VIBRATION_ENABLED, Boolean.toString(shouldVibrate()));
record.put(ATT_USER_LOCKED, Integer.toString(getUserLockedFields()));
record.put(ATT_VIBRATION, longArrayToString(getVibrationPattern()));
@@ -669,6 +695,7 @@
if (mBypassDnd != that.mBypassDnd) return false;
if (getLockscreenVisibility() != that.getLockscreenVisibility()) return false;
if (mLights != that.mLights) return false;
+ if (getLightColor() != that.getLightColor()) return false;
if (getUserLockedFields() != that.getUserLockedFields()) return false;
if (mVibrationEnabled != that.mVibrationEnabled) return false;
if (mShowBadge != that.mShowBadge) return false;
@@ -698,6 +725,7 @@
result = 31 * result + getLockscreenVisibility();
result = 31 * result + (getSound() != null ? getSound().hashCode() : 0);
result = 31 * result + (mLights ? 1 : 0);
+ result = 31 * result + getLightColor();
result = 31 * result + Arrays.hashCode(mVibration);
result = 31 * result + getUserLockedFields();
result = 31 * result + (mVibrationEnabled ? 1 : 0);
@@ -718,6 +746,7 @@
", mLockscreenVisibility=" + mLockscreenVisibility +
", mSound=" + mSound +
", mLights=" + mLights +
+ ", mLightColor=" + mLightColor +
", mVibration=" + Arrays.toString(mVibration) +
", mUserLockedFields=" + mUserLockedFields +
", mVibrationEnabled=" + mVibrationEnabled +
diff --git a/core/java/android/app/NotificationChannelGroup.java b/core/java/android/app/NotificationChannelGroup.java
index 68cac27..8854adc 100644
--- a/core/java/android/app/NotificationChannelGroup.java
+++ b/core/java/android/app/NotificationChannelGroup.java
@@ -170,6 +170,11 @@
}
@Override
+ public NotificationChannelGroup clone() {
+ return new NotificationChannelGroup(getId(), getName());
+ }
+
+ @Override
public int hashCode() {
int result = getId() != null ? getId().hashCode() : 0;
result = 31 * result + (getName() != null ? getName().hashCode() : 0);
diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java
index 57f18f1..0874095 100644
--- a/core/java/android/app/usage/UsageStats.java
+++ b/core/java/android/app/usage/UsageStats.java
@@ -138,13 +138,13 @@
mPackageName + "' with UsageStats for package '" + right.mPackageName + "'.");
}
+ // We use the mBeginTimeStamp due to a bug where UsageStats files can overlap with
+ // regards to their mEndTimeStamp.
if (right.mBeginTimeStamp > mBeginTimeStamp) {
- // The incoming UsageStat begins after this one, so use its last time used fields
- // as the source of truth.
- // We use the mBeginTimeStamp due to a bug where UsageStats files can overlap with
- // regards to their mEndTimeStamp.
- mLastEvent = right.mLastEvent;
- mLastTimeUsed = right.mLastTimeUsed;
+ // Even though incoming UsageStat begins after this one, its last time used fields
+ // may somehow be empty or chronologically preceding the older UsageStat.
+ mLastEvent = Math.max(mLastEvent, right.mLastEvent);
+ mLastTimeUsed = Math.max(mLastTimeUsed, right.mLastTimeUsed);
}
mBeginTimeStamp = Math.min(mBeginTimeStamp, right.mBeginTimeStamp);
mEndTimeStamp = Math.max(mEndTimeStamp, right.mEndTimeStamp);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 6a8141f..5f4c36c 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -6039,6 +6039,12 @@
case "--receiver-foreground":
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
break;
+ case "--receiver-no-abort":
+ intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);
+ break;
+ case "--receiver-include-background":
+ intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+ break;
case "--selector":
intent.setDataAndType(data, type);
intent = new Intent();
@@ -6162,7 +6168,8 @@
" [--activity-single-top] [--activity-clear-task]",
" [--activity-task-on-home]",
" [--receiver-registered-only] [--receiver-replace-pending]",
- " [--receiver-foreground]",
+ " [--receiver-foreground] [--receiver-no-abort]",
+ " [--receiver-include-background]",
" [--selector]",
" [<URI> | <PACKAGE> | <COMPONENT>]"
};
diff --git a/core/java/android/net/INetworkScoreService.aidl b/core/java/android/net/INetworkScoreService.aidl
index 82432c7..9cc256e 100644
--- a/core/java/android/net/INetworkScoreService.aidl
+++ b/core/java/android/net/INetworkScoreService.aidl
@@ -18,6 +18,7 @@
import android.net.INetworkScoreCache;
import android.net.NetworkKey;
+import android.net.NetworkScorerAppManager;
import android.net.RecommendationRequest;
import android.net.RecommendationResult;
import android.net.ScoredNetwork;
@@ -130,4 +131,6 @@
*/
oneway void requestRecommendationAsync(in RecommendationRequest request,
in RemoteCallback remoteCallback);
+
+ NetworkScorerAppManager.NetworkScorerAppData getActiveScorer();
}
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index 57cf1a5..2875580 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -186,6 +186,20 @@
}
/**
+ * Returns metadata about the active scorer or <code>null</code> if there is no active scorer.
+ *
+ * @hide
+ */
+ @Nullable
+ public NetworkScorerAppData getActiveScorer() {
+ try {
+ return mService.getActiveScorer();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Update network scores.
*
* <p>This may be called at any time to re-score active networks. Scores will generally be
diff --git a/core/java/android/net/NetworkScorerAppManager.aidl b/core/java/android/net/NetworkScorerAppManager.aidl
new file mode 100644
index 0000000..d968343
--- /dev/null
+++ b/core/java/android/net/NetworkScorerAppManager.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+parcelable NetworkScorerAppManager.NetworkScorerAppData;
diff --git a/core/java/android/net/NetworkScorerAppManager.java b/core/java/android/net/NetworkScorerAppManager.java
index 9dcf4f4..f3cbb52 100644
--- a/core/java/android/net/NetworkScorerAppManager.java
+++ b/core/java/android/net/NetworkScorerAppManager.java
@@ -24,6 +24,8 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
@@ -54,7 +56,7 @@
/**
* Holds metadata about a discovered network scorer/recommendation application.
*/
- public static class NetworkScorerAppData {
+ public static final class NetworkScorerAppData implements Parcelable {
/** UID of the scorer app. */
public final int packageUid;
private final ComponentName mRecommendationService;
@@ -64,6 +66,35 @@
this.mRecommendationService = recommendationServiceComp;
}
+ protected NetworkScorerAppData(Parcel in) {
+ packageUid = in.readInt();
+ mRecommendationService = ComponentName.readFromParcel(in);
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(packageUid);
+ ComponentName.writeToParcel(mRecommendationService, dest);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Creator<NetworkScorerAppData> CREATOR =
+ new Creator<NetworkScorerAppData>() {
+ @Override
+ public NetworkScorerAppData createFromParcel(Parcel in) {
+ return new NetworkScorerAppData(in);
+ }
+
+ @Override
+ public NetworkScorerAppData[] newArray(int size) {
+ return new NetworkScorerAppData[size];
+ }
+ };
+
public String getRecommendationServicePackageName() {
return mRecommendationService.getPackageName();
}
diff --git a/core/java/android/net/ScoredNetwork.java b/core/java/android/net/ScoredNetwork.java
index d396b50..ba0a8b5 100644
--- a/core/java/android/net/ScoredNetwork.java
+++ b/core/java/android/net/ScoredNetwork.java
@@ -106,7 +106,7 @@
* the Network Recommendation Provider.
*
* @see #ATTRIBUTES_KEY_HAS_CAPTIVE_PORTAL
- * @see #ATTRIBUTES_KEY_RANKING_SCORE_OFFSET_KEY
+ * @see #ATTRIBUTES_KEY_RANKING_SCORE_OFFSET
*/
@Nullable
public final Bundle attributes;
diff --git a/core/java/android/net/WifiKey.java b/core/java/android/net/WifiKey.java
index 99de99e..68b505d 100644
--- a/core/java/android/net/WifiKey.java
+++ b/core/java/android/net/WifiKey.java
@@ -64,10 +64,10 @@
* @throws IllegalArgumentException if either the SSID or BSSID is invalid.
*/
public WifiKey(String ssid, String bssid) {
- if (!SSID_PATTERN.matcher(ssid).matches()) {
+ if (ssid == null || !SSID_PATTERN.matcher(ssid).matches()) {
throw new IllegalArgumentException("Invalid ssid: " + ssid);
}
- if (!BSSID_PATTERN.matcher(bssid).matches()) {
+ if (bssid == null || !BSSID_PATTERN.matcher(bssid).matches()) {
throw new IllegalArgumentException("Invalid bssid: " + bssid);
}
this.ssid = ssid;
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 263750a..3a441c7 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -201,6 +201,11 @@
*/
public static final int BATTERY_PROPERTY_ENERGY_COUNTER = 5;
+ /**
+ * Battery charge status, from a BATTERY_STATUS_* value.
+ */
+ public static final int BATTERY_PROPERTY_BATTERY_STATUS = 6;
+
private final IBatteryStats mBatteryStats;
private final IBatteryPropertiesRegistrar mBatteryPropertiesRegistrar;
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 210ddb6..e05bd89 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -2219,11 +2219,13 @@
}
/**
- * Have the stack traces of the given native process dumped to the
- * specified file. Will be appended to the file.
+ * Append the stack traces of a given native process to a specified file.
+ * @param pid pid to dump.
+ * @param file path of file to append dump to.
+ * @param timeoutSecs time to wait in seconds, or 0 to wait forever.
* @hide
*/
- public static native void dumpNativeBacktraceToFile(int pid, String file);
+ public static native void dumpNativeBacktraceToFileTimeout(int pid, String file, int timeoutSecs);
/**
* Get description of unreachable native memory.
diff --git a/core/java/android/service/textservice/SpellCheckerService.java b/core/java/android/service/textservice/SpellCheckerService.java
index 120a37a..bd1b44c 100644
--- a/core/java/android/service/textservice/SpellCheckerService.java
+++ b/core/java/android/service/textservice/SpellCheckerService.java
@@ -17,6 +17,7 @@
package android.service.textservice;
import com.android.internal.textservice.ISpellCheckerService;
+import com.android.internal.textservice.ISpellCheckerServiceCallback;
import com.android.internal.textservice.ISpellCheckerSession;
import com.android.internal.textservice.ISpellCheckerSessionListener;
@@ -311,16 +312,39 @@
mInternalServiceRef = new WeakReference<SpellCheckerService>(service);
}
+ /**
+ * Called from the system when an application is requesting a new spell checker session.
+ *
+ * <p>Note: This is an internal protocol used by the system to establish spell checker
+ * sessions, which is not guaranteed to be stable and is subject to change.</p>
+ *
+ * @param locale locale to be returned from {@link Session#getLocale()}
+ * @param listener IPC channel object to be used to implement
+ * {@link Session#onGetSuggestionsMultiple(TextInfo[], int, boolean)} and
+ * {@link Session#onGetSuggestions(TextInfo, int)}
+ * @param bundle bundle to be returned from {@link Session#getBundle()}
+ * @param callback IPC channel to return the result to the caller in an asynchronous manner
+ */
@Override
- public ISpellCheckerSession getISpellCheckerSession(
- String locale, ISpellCheckerSessionListener listener, Bundle bundle) {
+ public void getISpellCheckerSession(
+ String locale, ISpellCheckerSessionListener listener, Bundle bundle,
+ ISpellCheckerServiceCallback callback) {
final SpellCheckerService service = mInternalServiceRef.get();
- if (service == null) return null;
- final Session session = service.createSession();
- final InternalISpellCheckerSession internalSession =
- new InternalISpellCheckerSession(locale, listener, bundle, session);
- session.onCreate();
- return internalSession;
+ final InternalISpellCheckerSession internalSession;
+ if (service == null) {
+ // If the owner SpellCheckerService object was already destroyed and got GC-ed,
+ // the weak-reference returns null and we should just ignore this request.
+ internalSession = null;
+ } else {
+ final Session session = service.createSession();
+ internalSession =
+ new InternalISpellCheckerSession(locale, listener, bundle, session);
+ session.onCreate();
+ }
+ try {
+ callback.onSessionCreated(internalSession);
+ } catch (RemoteException e) {
+ }
}
}
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index e9bbc2d..ca736e3 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -135,6 +135,7 @@
FrameLayout mContentFrame;
SoftInputWindow mWindow;
+ boolean mUiEnabled = true;
boolean mInitialized;
boolean mWindowAdded;
boolean mWindowVisible;
@@ -1001,35 +1002,40 @@
try {
mInShowWindow = true;
+ onPrepareShow(args, flags);
if (!mWindowVisible) {
- if (!mWindowAdded) {
- mWindowAdded = true;
- View v = onCreateContentView();
- if (v != null) {
- setContentView(v);
- }
- }
+ ensureWindowAdded();
}
onShow(args, flags);
if (!mWindowVisible) {
mWindowVisible = true;
- mWindow.show();
+ if (mUiEnabled) {
+ mWindow.show();
+ }
}
if (showCallback != null) {
- mRootView.invalidate();
- mRootView.getViewTreeObserver().addOnPreDrawListener(
- new ViewTreeObserver.OnPreDrawListener() {
- @Override
- public boolean onPreDraw() {
- mRootView.getViewTreeObserver().removeOnPreDrawListener(this);
- try {
- showCallback.onShown();
- } catch (RemoteException e) {
- Log.w(TAG, "Error calling onShown", e);
+ if (mUiEnabled) {
+ mRootView.invalidate();
+ mRootView.getViewTreeObserver().addOnPreDrawListener(
+ new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ mRootView.getViewTreeObserver().removeOnPreDrawListener(this);
+ try {
+ showCallback.onShown();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error calling onShown", e);
+ }
+ return true;
}
- return true;
- }
- });
+ });
+ } else {
+ try {
+ showCallback.onShown();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error calling onShown", e);
+ }
+ }
}
} finally {
mWindowWasVisible = true;
@@ -1039,7 +1045,7 @@
void doHide() {
if (mWindowVisible) {
- mWindow.hide();
+ ensureWindowHidden();
mWindowVisible = false;
onHide();
}
@@ -1058,19 +1064,56 @@
}
}
- void initViews() {
+ void ensureWindowCreated() {
+ if (mInitialized) {
+ return;
+ }
+
+ if (!mUiEnabled) {
+ throw new IllegalStateException("setUiEnabled is false");
+ }
+
mInitialized = true;
+ mInflater = (LayoutInflater)mContext.getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+ mWindow = new SoftInputWindow(mContext, "VoiceInteractionSession", mTheme,
+ mCallbacks, this, mDispatcherState,
+ WindowManager.LayoutParams.TYPE_VOICE_INTERACTION, Gravity.BOTTOM, true);
+ mWindow.getWindow().addFlags(
+ WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED |
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
+ WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR);
mThemeAttrs = mContext.obtainStyledAttributes(android.R.styleable.VoiceInteractionSession);
mRootView = mInflater.inflate(
com.android.internal.R.layout.voice_interaction_session, null);
mRootView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
- | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
+ | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
mWindow.setContentView(mRootView);
mRootView.getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsComputer);
mContentFrame = (FrameLayout)mRootView.findViewById(android.R.id.content);
+
+ mWindow.getWindow().setLayout(MATCH_PARENT, MATCH_PARENT);
+ mWindow.setToken(mToken);
+ }
+
+ void ensureWindowAdded() {
+ if (mUiEnabled && !mWindowAdded) {
+ mWindowAdded = true;
+ ensureWindowCreated();
+ View v = onCreateContentView();
+ if (v != null) {
+ setContentView(v);
+ }
+ }
+ }
+
+ void ensureWindowHidden() {
+ if (mWindow != null) {
+ mWindow.hide();
+ }
}
/**
@@ -1151,6 +1194,24 @@
}
/**
+ * Control whether the UI layer for this session is enabled. It is enabled by default.
+ * If set to false, you will not be able to provide a UI through {@link #onCreateContentView()}.
+ */
+ public void setUiEnabled(boolean enabled) {
+ if (mUiEnabled != enabled) {
+ mUiEnabled = enabled;
+ if (mWindowVisible) {
+ if (enabled) {
+ ensureWindowAdded();
+ mWindow.show();
+ } else {
+ ensureWindowHidden();
+ }
+ }
+ }
+ }
+
+ /**
* You can call this to customize the theme used by your IME's window.
* This must be set before {@link #onCreate}, so you
* will typically call it in your constructor with the resource ID
@@ -1242,6 +1303,7 @@
* Convenience for inflating views.
*/
public LayoutInflater getLayoutInflater() {
+ ensureWindowCreated();
return mInflater;
}
@@ -1249,6 +1311,7 @@
* Retrieve the window being used to show the session's UI.
*/
public Dialog getWindow() {
+ ensureWindowCreated();
return mWindow;
}
@@ -1278,18 +1341,17 @@
private void doOnCreate() {
mTheme = mTheme != 0 ? mTheme
: com.android.internal.R.style.Theme_DeviceDefault_VoiceInteractionSession;
- mInflater = (LayoutInflater)mContext.getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
- mWindow = new SoftInputWindow(mContext, "VoiceInteractionSession", mTheme,
- mCallbacks, this, mDispatcherState,
- WindowManager.LayoutParams.TYPE_VOICE_INTERACTION, Gravity.BOTTOM, true);
- mWindow.getWindow().addFlags(
- WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED |
- WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
- WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR);
- initViews();
- mWindow.getWindow().setLayout(MATCH_PARENT, MATCH_PARENT);
- mWindow.setToken(mToken);
+ }
+
+ /**
+ * Called prior to {@link #onShow} before any UI setup has occurred. Not generally useful.
+ *
+ * @param args The arguments that were supplied to
+ * {@link VoiceInteractionService#showSession VoiceInteractionService.showSession}.
+ * @param showFlags The show flags originally provided to
+ * {@link VoiceInteractionService#showSession VoiceInteractionService.showSession}.
+ */
+ public void onPrepareShow(Bundle args, int showFlags) {
}
/**
@@ -1327,6 +1389,7 @@
}
public void setContentView(View view) {
+ ensureWindowCreated();
mContentFrame.removeAllViews();
mContentFrame.addView(view, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
@@ -1623,7 +1686,8 @@
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
writer.print(prefix); writer.print("mToken="); writer.println(mToken);
writer.print(prefix); writer.print("mTheme=#"); writer.println(Integer.toHexString(mTheme));
- writer.print(prefix); writer.print("mInitialized="); writer.println(mInitialized);
+ writer.print(prefix); writer.print("mUiEnabled="); writer.println(mUiEnabled);
+ writer.print(" mInitialized="); writer.println(mInitialized);
writer.print(prefix); writer.print("mWindowAdded="); writer.print(mWindowAdded);
writer.print(" mWindowVisible="); writer.println(mWindowVisible);
writer.print(prefix); writer.print("mWindowWasVisible="); writer.print(mWindowWasVisible);
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index 80d3c8a..08df64f 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -409,6 +409,10 @@
return getSecureSettingInt(Settings.Secure.TTS_DEFAULT_RATE, Engine.DEFAULT_RATE);
}
+ private int getDefaultPitch() {
+ return getSecureSettingInt(Settings.Secure.TTS_DEFAULT_PITCH, Engine.DEFAULT_PITCH);
+ }
+
private String[] getSettingsLocale() {
final Locale locale = mEngineHelper.getLocalePrefForEngine(mPackageName);
return TtsEngines.toOldLocaleStringFormat(locale);
@@ -936,7 +940,7 @@
}
int getPitch() {
- return getIntParam(mParams, Engine.KEY_PARAM_PITCH, Engine.DEFAULT_PITCH);
+ return getIntParam(mParams, Engine.KEY_PARAM_PITCH, getDefaultPitch());
}
@Override
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 55aeb1e..ac9c0d7 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -456,10 +456,7 @@
* @return true if str is null or zero length
*/
public static boolean isEmpty(@Nullable CharSequence str) {
- if (str == null || str.length() == 0)
- return true;
- else
- return false;
+ return str == null || str.length() == 0;
}
/** {@hide} */
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 4ff4840..77e9f0f 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -42,7 +42,6 @@
import com.android.internal.R;
import com.android.internal.os.SomeArgs;
-import com.android.internal.util.Predicate;
import java.util.ArrayList;
import java.util.HashMap;
@@ -51,6 +50,7 @@
import java.util.List;
import java.util.Map;
import java.util.Queue;
+import java.util.function.Predicate;
/**
* Class for managing accessibility interactions initiated from the system
@@ -1205,7 +1205,7 @@
}
@Override
- public boolean apply(View view) {
+ public boolean test(View view) {
if (view.getId() == mViewId && isShown(view)) {
mInfos.add(view.createAccessibilityNodeInfo());
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ee97984..b06c3fd 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -16,12 +16,6 @@
package android.view;
-import static android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH;
-import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
-import static android.os.Build.VERSION_CODES.KITKAT;
-import static android.os.Build.VERSION_CODES.M;
-import static android.os.Build.VERSION_CODES.N;
-
import static java.lang.Math.max;
import android.animation.AnimatorInflater;
@@ -67,7 +61,7 @@
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.hardware.display.DisplayManagerGlobal;
-import android.os.Build.VERSION_CODES;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -106,7 +100,6 @@
import android.view.autofill.AutoFillManager;
import android.view.autofill.AutoFillType;
import android.view.autofill.AutoFillValue;
-import android.view.autofill.VirtualViewDelegate;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
@@ -115,7 +108,6 @@
import android.widget.ScrollBarDrawable;
import com.android.internal.R;
-import com.android.internal.util.Predicate;
import com.android.internal.view.TooltipPopup;
import com.android.internal.view.menu.MenuBuilder;
import com.android.internal.widget.ScrollBarUtils;
@@ -140,6 +132,7 @@
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Predicate;
/**
* <p>
@@ -857,6 +850,14 @@
*/
static boolean sCascadedDragDrop;
+ /**
+ * Prior to O, auto-focusable didn't exist and widgets such as ListView use hasFocusable
+ * to determine things like whether or not to permit item click events. We can't break
+ * apps that do this just because more things (clickable things) are now auto-focusable
+ * and they would get different results, so give old behavior to old apps.
+ */
+ static boolean sHasFocusableExcludeAutoFocusable;
+
/** @hide */
@IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO})
@Retention(RetentionPolicy.SOURCE)
@@ -4143,40 +4144,43 @@
final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
// Older apps may need this compatibility hack for measurement.
- sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
+ sUseBrokenMakeMeasureSpec = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
// Older apps expect onMeasure() to always be called on a layout pass, regardless
// of whether a layout was requested on that View.
- sIgnoreMeasureCache = targetSdkVersion < KITKAT;
+ sIgnoreMeasureCache = targetSdkVersion < Build.VERSION_CODES.KITKAT;
- Canvas.sCompatibilityRestore = targetSdkVersion < M;
+ Canvas.sCompatibilityRestore = targetSdkVersion < Build.VERSION_CODES.M;
// In M and newer, our widgets can pass a "hint" value in the size
// for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
// know what the expected parent size is going to be, so e.g. list items can size
// themselves at 1/3 the size of their container. It breaks older apps though,
// specifically apps that use some popular open source libraries.
- sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
+ sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < Build.VERSION_CODES.M;
// Old versions of the platform would give different results from
// LinearLayout measurement passes using EXACTLY and non-EXACTLY
// modes, so we always need to run an additional EXACTLY pass.
- sAlwaysRemeasureExactly = targetSdkVersion <= M;
+ sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
// Prior to N, layout params could change without requiring a
// subsequent call to setLayoutParams() and they would usually
// work. Partial layout breaks this assumption.
- sLayoutParamsAlwaysChanged = targetSdkVersion <= M;
+ sLayoutParamsAlwaysChanged = targetSdkVersion <= Build.VERSION_CODES.M;
// Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
// On N+, we throw, but that breaks compatibility with apps that use these methods.
- sTextureViewIgnoresDrawableSetters = targetSdkVersion <= M;
+ sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
// Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
// in apps so we target check it to avoid breaking existing apps.
- sPreserveMarginParamsInLayoutParamConversion = targetSdkVersion >= N;
+ sPreserveMarginParamsInLayoutParamConversion =
+ targetSdkVersion >= Build.VERSION_CODES.N;
- sCascadedDragDrop = targetSdkVersion < N;
+ sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N;
+
+ sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O;
sCompatibilityDone = true;
}
@@ -4525,7 +4529,7 @@
break;
//noinspection deprecation
case R.styleable.View_fadingEdge:
- if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
+ if (targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
// Ignore the attribute starting with ICS
break;
}
@@ -4663,27 +4667,27 @@
PROVIDER_BACKGROUND));
break;
case R.styleable.View_foreground:
- if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
+ if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
setForeground(a.getDrawable(attr));
}
break;
case R.styleable.View_foregroundGravity:
- if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
+ if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
}
break;
case R.styleable.View_foregroundTintMode:
- if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
+ if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
}
break;
case R.styleable.View_foregroundTint:
- if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
+ if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
setForegroundTintList(a.getColorStateList(attr));
}
break;
case R.styleable.View_foregroundInsidePadding:
- if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
+ if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
if (mForegroundInfo == null) {
mForegroundInfo = new ForegroundInfo();
}
@@ -6121,9 +6125,7 @@
if (mParent != null) {
mParent.requestChildFocus(this, this);
- if (mParent instanceof ViewGroup) {
- ((ViewGroup) mParent).setDefaultFocus(this);
- }
+ setFocusedInCluster();
}
if (mAttachInfo != null) {
@@ -6344,26 +6346,51 @@
/**
* Returns true if this view is focusable or if it contains a reachable View
- * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
- * is a View whose parents do not block descendants focus.
- *
+ * for which {@link #hasFocusable()} returns {@code true}. A "reachable hasFocusable()"
+ * is a view whose parents do not block descendants focus.
* Only {@link #VISIBLE} views are considered focusable.
*
- * @return True if the view is focusable or if the view contains a focusable
- * View, false otherwise.
+ * <p>As of {@link Build.VERSION_CODES#O} views that are determined to be focusable
+ * through {@link #FOCUSABLE_AUTO} will also cause this method to return {@code true}.
+ * Apps that declare a {@link android.content.pm.ApplicationInfo#targetSdkVersion} of
+ * earlier than {@link Build.VERSION_CODES#O} will continue to see this method return
+ * {@code false} for views not explicitly marked as focusable.
+ * Use {@link #hasExplicitFocusable()} if you require the pre-{@link Build.VERSION_CODES#O}
+ * behavior.</p>
+ *
+ * @return {@code true} if the view is focusable or if the view contains a focusable
+ * view, {@code false} otherwise
*
* @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
* @see ViewGroup#getTouchscreenBlocksFocus()
+ * @see #hasExplicitFocusable()
*/
public boolean hasFocusable() {
- return hasFocusable(true);
+ return hasFocusable(!sHasFocusableExcludeAutoFocusable, false);
}
/**
- * @hide pending determination of whether this should be public or not.
- * Currently used for compatibility with old focusability expectations in ListView.
+ * Returns true if this view is focusable or if it contains a reachable View
+ * for which {@link #hasExplicitFocusable()} returns {@code true}.
+ * A "reachable hasExplicitFocusable()" is a view whose parents do not block descendants focus.
+ * Only {@link #VISIBLE} views for which {@link #getFocusable()} would return
+ * {@link #FOCUSABLE} are considered focusable.
+ *
+ * <p>This method preserves the pre-{@link Build.VERSION_CODES#O} behavior of
+ * {@link #hasFocusable()} in that only views explicitly set focusable will cause
+ * this method to return true. A view set to {@link #FOCUSABLE_AUTO} that resolves
+ * to focusable will not.</p>
+ *
+ * @return {@code true} if the view is focusable or if the view contains a focusable
+ * view, {@code false} otherwise
+ *
+ * @see #hasFocusable()
*/
- public boolean hasFocusable(boolean allowAutoFocus) {
+ public boolean hasExplicitFocusable() {
+ return hasFocusable(false, true);
+ }
+
+ boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
if (!isFocusableInTouchMode()) {
for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
final ViewGroup g = (ViewGroup) p;
@@ -6884,10 +6911,16 @@
/**
* Called when assist structure is being retrieved from a view as part of an auto-fill request.
*
- * <p>The structure must be filled according to the request type, which is set in the
- * {@code flags} parameter - see the documentation on each flag for more details.
+ * <p>When implementing this method, subclasses must also:
*
- * @param structure Fill in with structured view data. The default implementation
+ * <ol>
+ * <li>Implement {@link #autoFill(AutoFillValue)}, {@link #getAutoFillType()}
+ * and {@link #getAutoFillValue()}.
+ * <li>Call {@link android.view.autofill.AutoFillManager#virtualValueChanged(View, int,
+ * AutoFillValue)} when its value changed.
+ * </ol>
+ *
+ * @param structure Fill in with structured view data. The default implementation
* fills in all data that can be inferred from the view itself.
* @param flags optional flags (currently {@code 0}).
*/
@@ -6983,12 +7016,22 @@
* Called when assist structure is being retrieved from a view as part of an auto-fill request
* to generate additional virtual structure under this view.
*
- * <p>The defaullt implementation uses {@link #getAccessibilityNodeProvider()} to try to
+ * <p>The default implementation uses {@link #getAccessibilityNodeProvider()} to try to
* generate this from the view's virtual accessibility nodes, if any. You can override this
* for a more optimal implementation providing this data.
*
- * <p>The structure must be filled according to the request type, which is set in the
- * {@code flags} parameter - see the documentation on each flag for more details.
+ * <p>When implementing this method, subclasses must follow the rules below:
+ *
+ * <ol>
+ * <li>Also implement {@link #autoFillVirtual(int, AutoFillValue)} to auto-fill the virtual
+ * children.
+ * <li>Call {@link android.view.autofill.AutoFillManager#virtualFocusChanged(View, int, Rect,
+ * boolean)} when the focus inside the view changed.
+ * <li>Call {@link android.view.autofill.AutoFillManager#virtualValueChanged(View, int,
+ * AutoFillValue)} when the value of a child changed.
+ * <li>Call {@link android.view.autofill.AutoFillManager#reset()} when the auto-fill context
+ * of the view structure changed.
+ * </ol>
*
* @param structure Fill in with structured view data.
* @param flags optional flags (currently {@code 0}).
@@ -7012,28 +7055,17 @@
}
/**
- * Gets the {@link VirtualViewDelegate} responsible for auto-filling the virtual children of
- * this view.
- *
- * <p>By default returns {@code null} but should be overridden when view provides a virtual
- * hierachy on {@link #onProvideAutoFillVirtualStructure(ViewStructure, int)}.
- */
- @Nullable
- public VirtualViewDelegate getAutoFillVirtualViewDelegate() {
- return null;
- }
-
- /**
* Automatically fills the content of this view with the {@code value}.
*
- * <p>By default does nothing, but views should override it (and {@link #getAutoFillType()
- * and #getAutoFillValue()} to support the AutoFill Framework.
+ * <p>By default does nothing, but views should override it (and {@link #getAutoFillType()},
+ * {@link #getAutoFillValue()}, and {@link #onProvideAutoFillStructure(ViewStructure, int)}
+ * to support the AutoFill Framework.
*
* <p>Typically, it is implemented by:
*
* <ol>
- * <li>Call the proper getter method on {@link AutoFillValue} to fetch the actual value.
- * <li>Pass the actual value to the equivalent setter in the view.
+ * <li>Calling the proper getter method on {@link AutoFillValue} to fetch the actual value.
+ * <li>Passing the actual value to the equivalent setter in the view.
* <ol>
*
* <p>For example, a text-field view would call:
@@ -7044,15 +7076,29 @@
* setText(text);
* }
* </pre>
+ *
+ * @param value value to be auto-filled.
*/
public void autoFill(@SuppressWarnings("unused") AutoFillValue value) {
}
/**
- * Describes the auto-fill type that should be used on calls to
- * {@link #autoFill(AutoFillValue)} and
- * {@link VirtualViewDelegate#autoFill(int, AutoFillValue)}.
+ * Automatically fills the content of a virtual view with the {@code value}
*
+ * <p>See {@link #autoFill(AutoFillValue)} and
+ * {@link #onProvideAutoFillVirtualStructure(ViewStructure, int)} for more info.
+ *
+ * @param value value to be auto-filled.
+ * @param virtualId id identifying the virtual child inside the custom view.
+ */
+ public void autoFillVirtual(@SuppressWarnings("unused") int virtualId,
+ @SuppressWarnings("unused") AutoFillValue value) {
+ }
+
+ /**
+ * Describes the auto-fill type that should be used on calls to
+ * {@link #autoFill(AutoFillValue)} and {@link #autoFillVirtual(int, AutoFillValue)}.
+
* <p>By default returns {@code null}, but views should override it (and
* {@link #autoFill(AutoFillValue)} to support the AutoFill Framework.
*/
@@ -7171,6 +7217,9 @@
boolean blocked = forAutoFill ? isAutoFillBlocked() : isAssistBlocked();
if (!blocked) {
if (forAutoFill) {
+ // The auto-fill id needs to be unique, but its value doesn't matter,
+ // so it's better to reuse the accessibility id to save space.
+ structure.setAutoFillId(getAccessibilityViewId());
// NOTE: flags are not currently supported, hence 0
onProvideAutoFillStructure(structure, 0);
onProvideAutoFillVirtualStructure(structure, 0);
@@ -8679,7 +8728,7 @@
@ResolvedLayoutDir
public int getLayoutDirection() {
final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
- if (targetSdkVersion < JELLY_BEAN_MR1) {
+ if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
}
@@ -9194,6 +9243,19 @@
}
/**
+ * Sets this View as the one which receives focus the next time cluster navigation jumps
+ * to the cluster containing this View. This does NOT change focus even if the cluster
+ * containing this view is current.
+ *
+ * @hide
+ */
+ public void setFocusedInCluster() {
+ if (mParent instanceof ViewGroup) {
+ ((ViewGroup) mParent).setFocusInCluster(this);
+ }
+ }
+
+ /**
* Returns whether this View should receive focus when the focus is restored for the view
* hierarchy containing this view.
* <p>
@@ -9239,7 +9301,7 @@
if (isFocusedByDefault) {
((ViewGroup) mParent).setDefaultFocus(this);
} else {
- ((ViewGroup) mParent).cleanDefaultFocus(this);
+ ((ViewGroup) mParent).clearDefaultFocus(this);
}
}
}
@@ -9325,7 +9387,7 @@
final int id = mID;
return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
@Override
- public boolean apply(View t) {
+ public boolean test(View t) {
return t.mNextFocusForwardId == id;
}
});
@@ -9619,15 +9681,27 @@
}
/**
+ * Public for testing. This will request focus for whichever View was last focused within this
+ * cluster before a focus-jump out of it.
+ *
+ * @hide
+ */
+ public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
+ // Prioritize focusableByDefault over algorithmic focus selection.
+ if (restoreDefaultFocus()) {
+ return true;
+ }
+ return requestFocus(direction);
+ }
+
+ /**
* Gives focus to the default-focus view in the view hierarchy that has this view as a root.
* If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
- * Nested keyboard navigation clusters are excluded from the hierarchy.
*
- * @param direction The direction of the focus
* @return Whether this view or one of its descendants actually took focus
*/
- public boolean restoreDefaultFocus(@FocusDirection int direction) {
- return requestFocus(direction);
+ public boolean restoreDefaultFocus() {
+ return requestFocus(View.FOCUS_DOWN);
}
/**
@@ -15730,7 +15804,7 @@
*/
private boolean isRtlCompatibilityMode() {
final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
- return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
+ return targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1 || !hasRtlSupport();
}
/**
@@ -20002,7 +20076,7 @@
* @hide
*/
protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
- if (predicate.apply(this)) {
+ if (predicate.test(this)) {
return this;
}
return null;
@@ -24448,20 +24522,20 @@
}
}
- private class MatchIdPredicate implements Predicate<View> {
+ private static class MatchIdPredicate implements Predicate<View> {
public int mId;
@Override
- public boolean apply(View view) {
+ public boolean test(View view) {
return (view.mID == mId);
}
}
- private class MatchLabelForPredicate implements Predicate<View> {
+ private static class MatchLabelForPredicate implements Predicate<View> {
private int mLabeledId;
@Override
- public boolean apply(View view) {
+ public boolean test(View view) {
return (view.mLabelForId == mLabeledId);
}
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 36beaaa..fd3ff82 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -57,7 +57,6 @@
import android.view.animation.Transformation;
import com.android.internal.R;
-import com.android.internal.util.Predicate;
import java.util.ArrayList;
import java.util.Arrays;
@@ -66,6 +65,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.function.Predicate;
/**
* <p>
@@ -141,6 +141,8 @@
// The view contained within this ViewGroup (excluding nested keyboard navigation clusters)
// that is or contains a default-focus view.
private View mDefaultFocus;
+ // The last child of this ViewGroup which held focus within the current cluster
+ private View mFocusedInCluster;
/**
* A Transformation used when drawing children, to
@@ -724,7 +726,7 @@
if (mFocused != null) {
mFocused.unFocus(this);
mFocused = null;
- mDefaultFocus = null;
+ mFocusedInCluster = null;
}
super.handleFocusGainInternal(direction, previouslyFocusedRect);
}
@@ -754,14 +756,9 @@
}
}
- /**
- * Sets the specified child view as the default focus for this view and all its ancestors.
- * If the view is inside a keyboard navigation cluster, stops at the root of the cluster since
- * the cluster forms a separate keyboard navigation hierarchy from the default focus point of
- * view.
- */
void setDefaultFocus(View child) {
- if (child.isKeyboardNavigationCluster()) {
+ // Stop at any higher view which is explicitly focused-by-default
+ if (mDefaultFocus != null && mDefaultFocus.isFocusedByDefault()) {
return;
}
@@ -773,10 +770,56 @@
}
/**
- * Destroys the default focus chain.
+ * Clears the default-focus chain from {@param child} up to the first parent which has another
+ * default-focusable branch below it or until there is no default-focus chain.
+ *
+ * @param child
*/
- void cleanDefaultFocus(View child) {
- if (mDefaultFocus != child) {
+ void clearDefaultFocus(View child) {
+ // Stop at any higher view which is explicitly focused-by-default
+ if (mDefaultFocus != child && mDefaultFocus != null
+ && mDefaultFocus.isFocusedByDefault()) {
+ return;
+ }
+
+ mDefaultFocus = null;
+
+ // Search child siblings for default focusables.
+ for (int i = 0; i < mChildrenCount; ++i) {
+ View sibling = mChildren[i];
+ if (sibling.isFocusedByDefault()) {
+ mDefaultFocus = sibling;
+ return;
+ } else if (mDefaultFocus == null && sibling.hasDefaultFocus()) {
+ mDefaultFocus = sibling;
+ }
+ }
+
+ if (mParent instanceof ViewGroup) {
+ ((ViewGroup) mParent).clearDefaultFocus(this);
+ }
+ }
+
+ @Override
+ boolean hasDefaultFocus() {
+ return mDefaultFocus != null || super.hasDefaultFocus();
+ }
+
+ void setFocusInCluster(View child) {
+ // Stop at the root of the cluster
+ if (child.isKeyboardNavigationCluster()) {
+ return;
+ }
+
+ mFocusedInCluster = child;
+
+ if (mParent instanceof ViewGroup) {
+ ((ViewGroup) mParent).setFocusInCluster(this);
+ }
+ }
+
+ void clearFocusInCluster(View child) {
+ if (mFocusedInCluster != child) {
return;
}
@@ -784,19 +827,14 @@
return;
}
- mDefaultFocus = null;
+ mFocusedInCluster = null;
if (mParent instanceof ViewGroup) {
- ((ViewGroup) mParent).cleanDefaultFocus(this);
+ ((ViewGroup) mParent).clearFocusInCluster(this);
}
}
@Override
- boolean hasDefaultFocus() {
- return mDefaultFocus != null || super.hasDefaultFocus();
- }
-
- @Override
public void focusableViewAvailable(View v) {
if (mParent != null
// shortcut: don't report a new focusable view if we block our descendants from
@@ -1107,14 +1145,15 @@
return null;
}
- /** @hide Overriding hidden method */
@Override
- public boolean hasFocusable(boolean allowAutoFocus) {
+ boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
return false;
}
- // TODO This should probably be super.hasFocusable, but that would change behavior
+ // TODO This should probably be super.hasFocusable, but that would change behavior.
+ // The below is a much simpler check than we do in the superclass implementation,
+ // but it's been this way for a long time and other code likely relies on it.
if ((allowAutoFocus ? getFocusable() != NOT_FOCUSABLE : getFocusable() == FOCUSABLE)
&& isFocusable()) {
return true;
@@ -1127,7 +1166,11 @@
for (int i = 0; i < count; i++) {
final View child = children[i];
- if (child.hasFocusable(allowAutoFocus)) {
+
+ // In case the subclass has overridden has[Explicit]Focusable, dispatch
+ // to the expected one for each child even though we share logic here.
+ if ((dispatchExplicit && child.hasExplicitFocusable())
+ || (!dispatchExplicit && child.hasFocusable())) {
return true;
}
}
@@ -3110,14 +3153,28 @@
}
@Override
- public boolean restoreDefaultFocus(@FocusDirection int direction) {
- if (mDefaultFocus != null && !mDefaultFocus.isKeyboardNavigationCluster()
+ public boolean restoreDefaultFocus() {
+ if (mDefaultFocus != null
&& getDescendantFocusability() != FOCUS_BLOCK_DESCENDANTS
&& (mDefaultFocus.mViewFlags & VISIBILITY_MASK) == VISIBLE
- && mDefaultFocus.restoreDefaultFocus(direction)) {
+ && mDefaultFocus.restoreDefaultFocus()) {
return true;
}
- return super.restoreDefaultFocus(direction);
+ return super.restoreDefaultFocus();
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
+ if (mFocusedInCluster != null && !mFocusedInCluster.isKeyboardNavigationCluster()
+ && getDescendantFocusability() != FOCUS_BLOCK_DESCENDANTS
+ && (mFocusedInCluster.mViewFlags & VISIBILITY_MASK) == VISIBLE
+ && mFocusedInCluster.restoreFocusInCluster(direction)) {
+ return true;
+ }
+ return super.restoreFocusInCluster(direction);
}
/**
@@ -4275,7 +4332,7 @@
*/
@Override
protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
- if (predicate.apply(this)) {
+ if (predicate.test(this)) {
return this;
}
@@ -4999,8 +5056,8 @@
view.unFocus(null);
clearChildFocus = true;
}
- if (view == mDefaultFocus) {
- mDefaultFocus = null;
+ if (view == mFocusedInCluster) {
+ clearFocusInCluster(view);
}
view.clearAccessibilityFocus();
@@ -5023,6 +5080,9 @@
removeFromArray(index);
+ if (view == mDefaultFocus) {
+ clearDefaultFocus(view);
+ }
if (clearChildFocus) {
clearChildFocus(view);
if (!rootViewRequestFocus()) {
@@ -5098,6 +5158,7 @@
final View focused = mFocused;
final boolean detach = mAttachInfo != null;
boolean clearChildFocus = false;
+ View clearDefaultFocus = null;
final View[] children = mChildren;
@@ -5113,7 +5174,10 @@
clearChildFocus = true;
}
if (view == mDefaultFocus) {
- mDefaultFocus = null;
+ clearDefaultFocus = view;
+ }
+ if (view == mFocusedInCluster) {
+ clearFocusInCluster(view);
}
view.clearAccessibilityFocus();
@@ -5139,6 +5203,9 @@
removeFromArray(start, count);
+ if (clearDefaultFocus != null) {
+ clearDefaultFocus(clearDefaultFocus);
+ }
if (clearChildFocus) {
clearChildFocus(focused);
if (!rootViewRequestFocus()) {
@@ -5188,7 +5255,6 @@
boolean clearChildFocus = false;
needGlobalAttributesUpdate(false);
- mDefaultFocus = null;
for (int i = count - 1; i >= 0; i--) {
final View view = children[i];
@@ -5224,6 +5290,9 @@
children[i] = null;
}
+ if (mDefaultFocus != null) {
+ clearDefaultFocus(mDefaultFocus);
+ }
if (clearChildFocus) {
clearChildFocus(focused);
if (!rootViewRequestFocus()) {
@@ -5261,7 +5330,10 @@
child.clearFocus();
}
if (child == mDefaultFocus) {
- mDefaultFocus = null;
+ clearDefaultFocus(child);
+ }
+ if (child == mFocusedInCluster) {
+ clearFocusInCluster(child);
}
child.clearAccessibilityFocus();
@@ -6246,6 +6318,12 @@
Log.d(VIEW_LOG_TAG, output);
mDefaultFocus.debug(depth + 1);
}
+ if (mFocusedInCluster != null) {
+ output = debugIndent(depth);
+ output += "mFocusedInCluster";
+ Log.d(VIEW_LOG_TAG, output);
+ mFocusedInCluster.debug(depth + 1);
+ }
if (mChildrenCount != 0) {
output = debugIndent(depth);
output += "{";
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 9e8dda8..cb29053 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2162,7 +2162,7 @@
+ mView.hasFocus());
if (mView != null) {
if (!mView.hasFocus()) {
- mView.restoreDefaultFocus(View.FOCUS_FORWARD);
+ mView.restoreDefaultFocus();
if (DEBUG_INPUT_RESIZE) Log.v(mTag, "First: requested focused view="
+ mView.findFocus());
} else {
@@ -4441,7 +4441,14 @@
? focused.keyboardNavigationClusterSearch(null, direction)
: keyboardNavigationClusterSearch(null, direction);
- if (cluster != null && cluster.restoreDefaultFocus(View.FOCUS_DOWN)) {
+ // Since requestFocus only takes "real" focus directions (and therefore also
+ // restoreFocusInCluster), convert forward/backward focus into FOCUS_DOWN.
+ int realDirection = direction;
+ if (direction == View.FOCUS_FORWARD || direction == View.FOCUS_BACKWARD) {
+ realDirection = View.FOCUS_DOWN;
+ }
+
+ if (cluster != null && cluster.restoreFocusInCluster(realDirection)) {
return true;
}
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index 5bae594..cc19539 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -22,7 +22,6 @@
import android.view.autofill.AutoFillId;
import android.view.autofill.AutoFillType;
import android.view.autofill.AutoFillValue;
-import android.view.autofill.VirtualViewDelegate;
/**
* Container for storing additional per-view data generated by {@link View#onProvideStructure
@@ -272,12 +271,11 @@
/**
* Like {@link #newChild(int)}, but providing a {@code virtualId} to the child so it can be
- * auto-filled by {@link VirtualViewDelegate#autoFill(int, AutoFillValue)}.
+ * auto-filled by {@link View#autoFillVirtual(int, AutoFillValue)}.
*
* @param index child index
- * @param virtualId child's id as defined by {@link VirtualViewDelegate#autoFill(int,
- * AutoFillValue)}.
- * @param flags currently either {@code 0} or {@link #AUTO_FILL_FLAG_SANITIZED}.
+ * @param virtualId id identifying the virtual child inside the custom view.
+ * @param flags currently {@code 0}.
*/
// TODO(b/33197203, b/33802548): add CTS/unit test
public abstract ViewStructure newChild(int index, int virtualId, int flags);
@@ -294,12 +292,11 @@
/**
* Like {@link #asyncNewChild(int)}, but providing a {@code virtualId} to the child so it can be
- * auto-filled by {@link VirtualViewDelegate#autoFill(int, AutoFillValue)}.
+ * auto-filled by {@link View#autoFillVirtual(int, AutoFillValue)}.
*
* @param index child index
- * @param virtualId child's id as defined by {@link VirtualViewDelegate#autoFill(int,
- * AutoFillValue)}.
- * @param flags currently either {@code 0} or {@link #AUTO_FILL_FLAG_SANITIZED}.
+ * @param virtualId id identifying the virtual child inside the custom view.
+ * @param flags currently {@code 0}.
*/
// TODO(b/33197203, b/33802548): add CTS/unit test
public abstract ViewStructure asyncNewChild(int index, int virtualId, int flags);
diff --git a/core/java/android/view/autofill/AutoFillManager.java b/core/java/android/view/autofill/AutoFillManager.java
index 6c20f07..58607ba 100644
--- a/core/java/android/view/autofill/AutoFillManager.java
+++ b/core/java/android/view/autofill/AutoFillManager.java
@@ -90,16 +90,13 @@
* @param parent parent view whose focus changed.
* @param childId id identifying the virtual child inside the parent view.
* @param bounds child boundaries, relative to the top window.
- * @param value current value of the child; can be {@code null} when focus is lost, but must be
- * set when focus is gained.
* @param gainFocus whether focus was gained or lost.
*/
- public void virtualFocusChanged(View parent, int childId, Rect bounds,
- @Nullable AutoFillValue value, boolean gainFocus) {
+ public void virtualFocusChanged(View parent, int childId, Rect bounds, boolean gainFocus) {
if (mSession == null) {
// Starts new session.
final AutoFillId id = getAutoFillId(parent, childId);
- startSession(id, bounds, value);
+ startSession(id, bounds, null);
return;
}
@@ -110,7 +107,7 @@
// Update focus on existing session.
final AutoFillId id = getAutoFillId(parent, childId);
- updateSession(id, bounds, value, gainFocus ? FLAG_FOCUS_GAINED : FLAG_FOCUS_LOST);
+ updateSession(id, bounds, null, gainFocus ? FLAG_FOCUS_GAINED : FLAG_FOCUS_LOST);
}
/**
diff --git a/core/java/android/view/autofill/AutoFillSession.java b/core/java/android/view/autofill/AutoFillSession.java
index e10ba37..64df62f 100644
--- a/core/java/android/view/autofill/AutoFillSession.java
+++ b/core/java/android/view/autofill/AutoFillSession.java
@@ -68,24 +68,9 @@
continue;
}
- // TODO(b/33197203): handle protected value (like credit card)
if (id.isVirtual()) {
- // Delegate virtual fields.
- final VirtualViewDelegate delegate = view
- .getAutoFillVirtualViewDelegate();
- if (delegate == null) {
- Log.w(TAG, "autoFill(): cannot fill virtual " + id
- + "; no VirtualViewDelegate for view "
- + view.getClass());
- continue;
- }
- if (DEBUG) {
- Log.d(TAG, "autoFill(): delegating " + id
- + " to VirtualViewDelegate " + delegate);
- }
- delegate.autoFill(id.getVirtualChildId(), value);
+ view.autoFillVirtual(id.getVirtualChildId(), value);
} else {
- // Handle non-virtual fields itself.
view.autoFill(value);
}
}
diff --git a/core/java/android/view/autofill/VirtualViewDelegate.java b/core/java/android/view/autofill/VirtualViewDelegate.java
deleted file mode 100644
index 3dda7f7..0000000
--- a/core/java/android/view/autofill/VirtualViewDelegate.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2016 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.view.autofill;
-
-import android.view.View;
-import android.view.ViewStructure;
-
-/**
- * This class is the contract a client should implement to enable support of a
- * virtual view hierarchy rooted at a given view for auto-fill purposes.
- *
- * <p>The view hierarchy is typically created through the
- * {@link View#onProvideAutoFillVirtualStructure(android.view.ViewStructure, int)} call and client
- * add virtual children by calling {@link ViewStructure#newChild(int, int, int)} or
- * {@link ViewStructure#asyncNewChild(int, int, int)}, where the client provides the
- * {@code virtualId} of the children - the same {@code virtualId} is used in the methods of this
- * class.
- *
- * <p>Objects of this class are typically created by overriding
- * {@link View#getAutoFillVirtualViewDelegate()} and saving the passed callback, which must
- * be notified upon changes on the hierarchy.
- *
- * <p>The main use case of these API is to enable custom views that draws its content - such as
- * {@link android.webkit.WebView} providers - to support the AutoFill Framework:
- *
- * <ol>
- * <li>Client populates the virtual hierarchy on
- * {@link View#onProvideAutoFillVirtualStructure(android.view.ViewStructure, int)}
- * <li>Android System generates the proper {@link AutoFillId} - encapsulating the view and the
- * virtual child ids - and pass it to the {@link android.service.autofill.AutoFillService}.
- * <li>The service uses the {@link AutoFillId} to populate the auto-fill {@link Dataset}s and pass
- * it back to the Android System.
- * <li>Android System uses the {@link AutoFillId} to find the proper custom view and calls
- * {@link #autoFill(int, AutoFillValue)} on that view passing the virtual id.
- * <li>This provider than finds the child in the hierarchy and auto-fills it.
- * </ol>
- *
- */
-public abstract class VirtualViewDelegate {
-
- /**
- * Auto-fills a virtual view with the {@code value}.
- *
- * @param virtualId id identifying the virtual child inside the custom view.
- * @param value value to be auto-filled.
- */
- public abstract void autoFill(int virtualId, AutoFillValue value);
-}
diff --git a/core/java/android/view/textclassifier/TextClassificationManager.java b/core/java/android/view/textclassifier/TextClassificationManager.java
index a85dea9..a4e524f 100644
--- a/core/java/android/view/textclassifier/TextClassificationManager.java
+++ b/core/java/android/view/textclassifier/TextClassificationManager.java
@@ -41,6 +41,9 @@
private static final String LOG_TAG = "TextClassificationManager";
+ private final Object mTextClassifierLock = new Object();
+ private final Object mLangIdLock = new Object();
+
private final Context mContext;
// TODO: Implement a way to close the file descriptor.
private ParcelFileDescriptor mFd;
@@ -55,19 +58,21 @@
/**
* Returns the default text classifier.
*/
- public synchronized TextClassifier getDefaultTextClassifier() {
- if (mDefault == null) {
- try {
- mFd = ParcelFileDescriptor.open(
- new File("/etc/assistant/smart-selection.model"),
- ParcelFileDescriptor.MODE_READ_ONLY);
- mDefault = new TextClassifierImpl(mContext, mFd);
- } catch (FileNotFoundException e) {
- Log.e(LOG_TAG, "Error accessing 'text classifier selection' model file.", e);
- mDefault = TextClassifier.NO_OP;
+ public TextClassifier getDefaultTextClassifier() {
+ synchronized (mTextClassifierLock) {
+ if (mDefault == null) {
+ try {
+ mFd = ParcelFileDescriptor.open(
+ new File("/etc/assistant/smart-selection.model"),
+ ParcelFileDescriptor.MODE_READ_ONLY);
+ mDefault = new TextClassifierImpl(mContext, mFd);
+ } catch (FileNotFoundException e) {
+ Log.e(LOG_TAG, "Error accessing 'text classifier selection' model file.", e);
+ mDefault = TextClassifier.NO_OP;
+ }
}
+ return mDefault;
}
- return mDefault;
}
/**
@@ -95,12 +100,14 @@
return Collections.emptyList();
}
- private synchronized LangId getLanguageDetector() {
- if (mLangId == null) {
- // TODO: Use a file descriptor as soon as we start to depend on a model file
- // for language detection.
- mLangId = new LangId(0);
+ private LangId getLanguageDetector() {
+ synchronized (mLangIdLock) {
+ if (mLangId == null) {
+ // TODO: Use a file descriptor as soon as we start to depend on a model file
+ // for language detection.
+ mLangId = new LangId(0);
+ }
+ return mLangId;
}
- return mLangId;
}
}
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 7838918..e2ff44c 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -60,6 +60,8 @@
private static final String LOG_TAG = "TextClassifierImpl";
+ private final Object mSmartSelectionLock = new Object();
+
private final Context mContext;
private final ParcelFileDescriptor mFd;
private SmartSelection mSmartSelection;
@@ -140,11 +142,13 @@
return TextClassifier.NO_OP.getLinks(text, linkMask);
}
- private synchronized SmartSelection getSmartSelection() throws FileNotFoundException {
- if (mSmartSelection == null) {
- mSmartSelection = new SmartSelection(mFd.getFd());
+ private SmartSelection getSmartSelection() throws FileNotFoundException {
+ synchronized (mSmartSelectionLock) {
+ if (mSmartSelection == null) {
+ mSmartSelection = new SmartSelection(mFd.getFd());
+ }
+ return mSmartSelection;
}
- return mSmartSelection;
}
private TextClassificationResult createClassificationResult(String type, CharSequence text) {
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 47c4cf38..4c9a866 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2548,7 +2548,7 @@
}
private boolean isItemClickable(View view) {
- return !view.hasFocusable(false);
+ return !view.hasExplicitFocusable();
}
/**
@@ -2824,7 +2824,7 @@
final View v = getChildAt(mSelectedPosition - mFirstPosition);
if (v != null) {
- if (v.hasFocusable(false)) return;
+ if (v.hasExplicitFocusable()) return;
v.setPressed(true);
}
setPressed(true);
@@ -3428,7 +3428,7 @@
if (mTouchMode == TOUCH_MODE_DOWN) {
mTouchMode = TOUCH_MODE_TAP;
final View child = getChildAt(mMotionPosition - mFirstPosition);
- if (child != null && !child.hasFocusable(false)) {
+ if (child != null && !child.hasExplicitFocusable()) {
mLayoutMode = LAYOUT_NORMAL;
if (!mDataChanged) {
@@ -4005,7 +4005,7 @@
final float x = ev.getX();
final boolean inList = x > mListPadding.left && x < getWidth() - mListPadding.right;
- if (inList && !child.hasFocusable(false)) {
+ if (inList && !child.hasExplicitFocusable()) {
if (mPerformClick == null) {
mPerformClick = new PerformClick();
}
diff --git a/core/java/android/widget/DayPickerViewPager.java b/core/java/android/widget/DayPickerViewPager.java
index 94022ae..a27e022 100644
--- a/core/java/android/widget/DayPickerViewPager.java
+++ b/core/java/android/widget/DayPickerViewPager.java
@@ -21,10 +21,10 @@
import android.util.AttributeSet;
import android.view.View;
-import com.android.internal.util.Predicate;
import com.android.internal.widget.ViewPager;
import java.util.ArrayList;
+import java.util.function.Predicate;
/**
* This displays a list of months in a calendar format with selectable days.
@@ -138,7 +138,7 @@
@Override
protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
- if (predicate.apply(this)) {
+ if (predicate.test(this)) {
return this;
}
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 76ed80f..45b5570 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -106,7 +106,6 @@
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.view.textclassifier.TextClassificationResult;
-import android.view.textclassifier.TextSelection;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.TextView.Drawables;
import android.widget.TextView.OnEditorActionListener;
@@ -150,10 +149,10 @@
private static final int MENU_ITEM_ORDER_ASSIST = 1;
private static final int MENU_ITEM_ORDER_UNDO = 2;
private static final int MENU_ITEM_ORDER_REDO = 3;
- private static final int MENU_ITEM_ORDER_SHARE = 4;
- private static final int MENU_ITEM_ORDER_CUT = 5;
- private static final int MENU_ITEM_ORDER_COPY = 6;
- private static final int MENU_ITEM_ORDER_PASTE = 7;
+ private static final int MENU_ITEM_ORDER_CUT = 4;
+ private static final int MENU_ITEM_ORDER_COPY = 5;
+ private static final int MENU_ITEM_ORDER_PASTE = 6;
+ private static final int MENU_ITEM_ORDER_SHARE = 7;
private static final int MENU_ITEM_ORDER_PASTE_AS_PLAIN_TEXT = 8;
private static final int MENU_ITEM_ORDER_SELECT_ALL = 9;
private static final int MENU_ITEM_ORDER_REPLACE = 10;
@@ -169,7 +168,7 @@
private InsertionPointCursorController mInsertionPointCursorController;
SelectionModifierCursorController mSelectionModifierCursorController;
// Action mode used when text is selected or when actions on an insertion cursor are triggered.
- ActionMode mTextActionMode;
+ private ActionMode mTextActionMode;
private boolean mInsertionControllerEnabled;
private boolean mSelectionControllerEnabled;
@@ -236,7 +235,7 @@
private boolean mPreserveSelection;
private boolean mRestartActionModeOnNextRefresh;
- private TextClassificationResult mTextClassificationResult;
+ private SelectionActionModeHelper mSelectionActionModeHelper;
boolean mIsBeingLongClicked;
@@ -292,7 +291,7 @@
private Rect mTempRect;
- private TextView mTextView;
+ private final TextView mTextView;
final ProcessTextIntentActionsHandler mProcessTextIntentActionsHandler;
@@ -1850,7 +1849,7 @@
mInsertionPointCursorController.invalidateHandle();
}
if (mTextActionMode != null) {
- invalidateActionMode(getTextClassifierInfo(false));
+ invalidateActionModeAsync();
}
}
@@ -1943,12 +1942,12 @@
if (mRestartActionModeOnNextRefresh) {
// To avoid distraction, newly start action mode only when selection action
// mode is being restarted.
- startSelectionActionMode(null);
+ startSelectionActionMode();
}
} else if (selectionController == null || !selectionController.isActive()) {
// Insertion action mode is active. Avoid dismissing the selection.
stopTextActionModeWithPreservingSelection();
- startSelectionActionMode(null);
+ startSelectionActionMode();
} else {
mTextActionMode.invalidateContentRect();
}
@@ -1985,55 +1984,46 @@
}
}
+ @NonNull
+ TextView getTextView() {
+ return mTextView;
+ }
+
+ @Nullable
+ ActionMode getTextActionMode() {
+ return mTextActionMode;
+ }
+
+ void setRestartActionModeOnNextRefresh(boolean value) {
+ mRestartActionModeOnNextRefresh = value;
+ }
+
/**
- * Starts a Selection Action Mode with the current selection and ensures the selection handles
- * are shown if there is a selection. This should be used when the mode is started from a
- * non-touch event.
- *
- * @return true if the selection mode was actually started.
+ * Asynchronously starts a selection action mode using the TextClassifier.
*/
- boolean startSelectionActionMode(@Nullable TextClassificationResult textClassificationResult) {
- mTextClassificationResult = textClassificationResult;
- boolean selectionStarted = startSelectionActionModeInternal();
- if (selectionStarted) {
- getSelectionController().show();
+ void startSelectionActionModeAsync() {
+ getSelectionActionModeHelper().startActionModeAsync();
+ }
+
+ /**
+ * Synchronously starts a selection action mode without the TextClassifier.
+ */
+ void startSelectionActionMode() {
+ getSelectionActionModeHelper().startActionMode();
+ }
+
+ /**
+ * Asynchronously invalidates an action mode using the TextClassifier.
+ */
+ private void invalidateActionModeAsync() {
+ getSelectionActionModeHelper().invalidateActionModeAsync();
+ }
+
+ private SelectionActionModeHelper getSelectionActionModeHelper() {
+ if (mSelectionActionModeHelper == null) {
+ mSelectionActionModeHelper = new SelectionActionModeHelper(this);
}
- mRestartActionModeOnNextRefresh = false;
- return selectionStarted;
- }
-
- private boolean startSelectionActionModeWithTextAssistant() {
- return startSelectionActionMode(getTextClassifierInfo(true));
- }
-
- private void invalidateActionMode(TextClassificationResult textClassificationResult) {
- mTextClassificationResult = textClassificationResult;
- mTextActionMode.invalidate();
- }
-
- // TODO: Make this a non-blocking call.
- private TextClassificationResult getTextClassifierInfo(boolean updateSelection) {
- // TODO: Trim the text so that only text necessary to provide context of the selected
- // text is sent to the assistant.
- final int trimStartIndex = 0;
- final int trimEndIndex = mTextView.getText().length();
- CharSequence trimmedText =
- mTextView.getText().subSequence(trimStartIndex, trimEndIndex);
- int startIndex = mTextView.getSelectionStart() - trimStartIndex;
- int endIndex = mTextView.getSelectionEnd() - trimStartIndex;
-
- if (updateSelection) {
- TextSelection textSelection = mTextView.getTextClassifier()
- .suggestSelection(trimmedText, startIndex, endIndex);
- startIndex = Math.max(0, textSelection.getSelectionStartIndex() + trimStartIndex);
- endIndex = Math.min(mTextView.getText().length(),
- textSelection.getSelectionEndIndex() + trimStartIndex);
- Selection.setSelection((Spannable) mTextView.getText(), startIndex, endIndex);
- return getTextClassifierInfo(false);
- }
-
- return mTextView.getTextClassifier()
- .getTextClassificationResult(trimmedText, startIndex, endIndex);
+ return mSelectionActionModeHelper;
}
/**
@@ -2076,13 +2066,13 @@
return true;
}
- private boolean startSelectionActionModeInternal() {
+ boolean startSelectionActionModeInternal() {
if (extractedTextModeWillBeStarted()) {
return false;
}
if (mTextActionMode != null) {
// Text action mode is already started
- invalidateActionMode(getTextClassifierInfo(false));
+ invalidateActionModeAsync();
return false;
}
@@ -2273,7 +2263,8 @@
return mInsertionPointCursorController;
}
- private SelectionModifierCursorController getSelectionController() {
+ @Nullable
+ SelectionModifierCursorController getSelectionController() {
if (!mSelectionControllerEnabled) {
return null;
}
@@ -3772,7 +3763,7 @@
mode.setSubtitle(null);
mode.setTitleOptionalHint(true);
populateMenuWithItems(menu);
- updateAssistMenuItem(menu, mTextClassificationResult);
+ updateAssistMenuItem(menu);
Callback customCallback = getCustomCallback();
if (customCallback != null) {
@@ -3840,7 +3831,7 @@
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
updateSelectAllItem(menu);
updateReplaceItem(menu);
- updateAssistMenuItem(menu, mTextClassificationResult);
+ updateAssistMenuItem(menu);
Callback customCallback = getCustomCallback();
if (customCallback != null) {
@@ -3873,9 +3864,10 @@
}
}
- private void updateAssistMenuItem(
- Menu menu, TextClassificationResult textClassificationResult) {
+ private void updateAssistMenuItem(Menu menu) {
menu.removeItem(TextView.ID_ASSIST);
+ final TextClassificationResult textClassificationResult =
+ getSelectionActionModeHelper().getTextClassificationResult();
if (textClassificationResult != null) {
final Drawable icon = textClassificationResult.getIcon();
final CharSequence label = textClassificationResult.getLabel();
@@ -3884,7 +3876,7 @@
final Intent intent = textClassificationResult.getIntent();
if ((icon != null || !TextUtils.isEmpty(label))
&& (onClickListener != null || intent != null)) {
- menu.add(Menu.NONE, TextView.ID_ASSIST, MENU_ITEM_ORDER_ASSIST, label)
+ menu.add(TextView.ID_ASSIST, TextView.ID_ASSIST, MENU_ITEM_ORDER_ASSIST, label)
.setIcon(icon)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
}
@@ -3900,7 +3892,8 @@
if (customCallback != null && customCallback.onActionItemClicked(mode, item)) {
return true;
}
- final TextClassificationResult textClassificationResult = mTextClassificationResult;
+ final TextClassificationResult textClassificationResult =
+ getSelectionActionModeHelper().getTextClassificationResult();
if (TextView.ID_ASSIST == item.getItemId() && textClassificationResult != null) {
final OnClickListener onClickListener =
textClassificationResult.getOnClickListener();
@@ -3923,8 +3916,8 @@
@Override
public void onDestroyActionMode(ActionMode mode) {
// Clear mTextActionMode not to recursively destroy action mode by clearing selection.
+ getSelectionActionModeHelper().cancelAsyncTask();
mTextActionMode = null;
- mTextClassificationResult = null;
Callback customCallback = getCustomCallback();
if (customCallback != null) {
customCallback.onDestroyActionMode(mode);
@@ -4683,7 +4676,7 @@
}
positionAtCursorOffset(offset, false);
if (mTextActionMode != null) {
- invalidateActionMode(getTextClassifierInfo(false));
+ invalidateActionModeAsync();
}
}
@@ -4767,7 +4760,7 @@
}
updateDrawable();
if (mTextActionMode != null) {
- invalidateActionMode(getTextClassifierInfo(false));
+ invalidateActionModeAsync();
}
}
@@ -5416,8 +5409,12 @@
if (mTextView.hasSelection()) {
// Do not invoke the text assistant if this was a drag selection.
- startSelectionActionMode(
- mHaventMovedEnoughToStartDrag ? getTextClassifierInfo(true) : null);
+ if (mHaventMovedEnoughToStartDrag) {
+ startSelectionActionModeAsync();
+ } else {
+ startSelectionActionMode();
+ }
+
}
break;
}
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 80780a6..46e998a 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -49,12 +49,12 @@
import android.widget.RemoteViews.RemoteView;
import com.android.internal.R;
-import com.android.internal.util.Predicate;
import com.google.android.collect.Lists;
import java.util.ArrayList;
import java.util.List;
+import java.util.function.Predicate;
/*
* Implementation Notes:
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
new file mode 100644
index 0000000..770d9ee
--- /dev/null
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -0,0 +1,288 @@
+/*
+ * 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.widget;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UiThread;
+import android.annotation.WorkerThread;
+import android.os.AsyncTask;
+import android.text.Selection;
+import android.text.Spannable;
+import android.text.TextUtils;
+import android.view.ActionMode;
+import android.view.textclassifier.TextClassificationResult;
+import android.view.textclassifier.TextClassifier;
+import android.view.textclassifier.TextSelection;
+import android.widget.Editor.SelectionModifierCursorController;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+/**
+ * Helper class for starting selection action mode
+ * (synchronously without the TextClassifier, asynchronously with the TextClassifier).
+ */
+@UiThread
+final class SelectionActionModeHelper {
+
+ /**
+ * Maximum time (in milliseconds) to wait for a result before timing out.
+ */
+ // TODO: Consider making this a ViewConfiguration.
+ private static final int TIMEOUT_DURATION = 200;
+
+ private final Editor mEditor;
+ private final TextClassificationHelper mTextClassificationHelper;
+
+ private TextClassificationResult mTextClassificationResult;
+ private AsyncTask mTextClassificationAsyncTask;
+
+ SelectionActionModeHelper(@NonNull Editor editor) {
+ mEditor = Preconditions.checkNotNull(editor);
+ final TextView textView = mEditor.getTextView();
+ mTextClassificationHelper = new TextClassificationHelper(
+ textView.getTextClassifier(), textView.getText(),
+ textView.getSelectionStart(), textView.getSelectionEnd());
+ }
+
+ public void startActionModeAsync() {
+ cancelAsyncTask();
+ if (isNoOpTextClassifier()) {
+ // No need to make an async call for a no-op TextClassifier.
+ startActionMode(null);
+ } else {
+ resetTextClassificationHelper();
+ mTextClassificationAsyncTask = new TextClassificationAsyncTask(
+ mEditor.getTextView(), TIMEOUT_DURATION,
+ mTextClassificationHelper::suggestSelection, this::startActionMode)
+ .execute();
+ }
+ }
+
+ public void startActionMode() {
+ startActionMode(null);
+ }
+
+ public void invalidateActionModeAsync() {
+ cancelAsyncTask();
+ if (isNoOpTextClassifier()) {
+ // No need to make an async call for a no-op TextClassifier.
+ invalidateActionMode(null);
+ } else {
+ resetTextClassificationHelper();
+ mTextClassificationAsyncTask = new TextClassificationAsyncTask(
+ mEditor.getTextView(), TIMEOUT_DURATION,
+ mTextClassificationHelper::classifyText, this::invalidateActionMode)
+ .execute();
+ }
+ }
+
+ public void cancelAsyncTask() {
+ if (mTextClassificationAsyncTask != null) {
+ mTextClassificationAsyncTask.cancel(true);
+ mTextClassificationAsyncTask = null;
+ }
+ mTextClassificationResult = null;
+ }
+
+ @Nullable
+ public TextClassificationResult getTextClassificationResult() {
+ return mTextClassificationResult;
+ }
+
+ private boolean isNoOpTextClassifier() {
+ return mEditor.getTextView().getTextClassifier() == TextClassifier.NO_OP;
+ }
+
+ private void startActionMode(@Nullable SelectionResult result) {
+ final CharSequence text = mEditor.getTextView().getText();
+ if (result != null && text instanceof Spannable) {
+ Selection.setSelection((Spannable) text, result.mStart, result.mEnd);
+ mTextClassificationResult = result.mResult;
+ } else {
+ mTextClassificationResult = null;
+ }
+ if (mEditor.startSelectionActionModeInternal()) {
+ final SelectionModifierCursorController controller = mEditor.getSelectionController();
+ if (controller != null) {
+ controller.show();
+ }
+ }
+ mEditor.setRestartActionModeOnNextRefresh(false);
+ mTextClassificationAsyncTask = null;
+ }
+
+ private void invalidateActionMode(@Nullable SelectionResult result) {
+ mTextClassificationResult = result != null ? result.mResult : null;
+ final ActionMode actionMode = mEditor.getTextActionMode();
+ if (actionMode != null) {
+ actionMode.invalidate();
+ }
+ mTextClassificationAsyncTask = null;
+ }
+
+ private void resetTextClassificationHelper() {
+ final TextView textView = mEditor.getTextView();
+ mTextClassificationHelper.reset(textView.getTextClassifier(), textView.getText(),
+ textView.getSelectionStart(), textView.getSelectionEnd());
+ }
+
+ /**
+ * AsyncTask for running a query on a background thread and returning the result on the
+ * UiThread. The AsyncTask times out after a specified time, returning a null result if the
+ * query has not yet returned.
+ */
+ private static final class TextClassificationAsyncTask
+ extends AsyncTask<Void, Void, SelectionResult> {
+
+ private final int mTimeOutDuration;
+ private final Supplier<SelectionResult> mSelectionResultSupplier;
+ private final Consumer<SelectionResult> mSelectionResultCallback;
+ private final TextView mTextView;
+ private final String mOriginalText;
+
+ /**
+ * @param textView the TextView
+ * @param timeOut time in milliseconds to timeout the query if it has not completed
+ * @param selectionResultSupplier fetches the selection results. Runs on a background thread
+ * @param selectionResultCallback receives the selection results. Runs on the UiThread
+ */
+ TextClassificationAsyncTask(
+ @NonNull TextView textView, int timeOut,
+ @NonNull Supplier<SelectionResult> selectionResultSupplier,
+ @NonNull Consumer<SelectionResult> selectionResultCallback) {
+ mTextView = Preconditions.checkNotNull(textView);
+ mTimeOutDuration = timeOut;
+ mSelectionResultSupplier = Preconditions.checkNotNull(selectionResultSupplier);
+ mSelectionResultCallback = Preconditions.checkNotNull(selectionResultCallback);
+ // Make a copy of the original text.
+ mOriginalText = mTextView.getText().toString();
+ }
+
+ @Override
+ @WorkerThread
+ protected SelectionResult doInBackground(Void... params) {
+ final Runnable onTimeOut = this::onTimeOut;
+ mTextView.postDelayed(onTimeOut, mTimeOutDuration);
+ final SelectionResult result = mSelectionResultSupplier.get();
+ mTextView.removeCallbacks(onTimeOut);
+ return result;
+ }
+
+ @Override
+ @UiThread
+ protected void onPostExecute(SelectionResult result) {
+ result = TextUtils.equals(mOriginalText, mTextView.getText()) ? result : null;
+ mSelectionResultCallback.accept(result);
+ }
+
+ private void onTimeOut() {
+ if (getStatus() == Status.RUNNING) {
+ onPostExecute(null);
+ }
+ cancel(true);
+ }
+ }
+
+ /**
+ * Helper class for querying the TextClassifier.
+ * It trims text so that only text necessary to provide context of the selected text is
+ * sent to the TextClassifier.
+ */
+ private static final class TextClassificationHelper {
+
+ private static final int TRIM_DELTA = 50; // characters
+
+ private TextClassifier mTextClassifier;
+
+ /** The original TextView text. **/
+ private String mText;
+ /** Start index relative to mText. */
+ private int mSelectionStart;
+ /** End index relative to mText. */
+ private int mSelectionEnd;
+
+ /** Trimmed text starting from mTrimStart in mText. */
+ private CharSequence mTrimmedText;
+ /** Index indicating the start of mTrimmedText in mText. */
+ private int mTrimStart;
+ /** Start index relative to mTrimmedText */
+ private int mRelativeStart;
+ /** End index relative to mTrimmedText */
+ private int mRelativeEnd;
+
+ TextClassificationHelper(TextClassifier textClassifier,
+ CharSequence text, int selectionStart, int selectionEnd) {
+ reset(textClassifier, text, selectionStart, selectionEnd);
+ }
+
+ @UiThread
+ public void reset(TextClassifier textClassifier,
+ CharSequence text, int selectionStart, int selectionEnd) {
+ mTextClassifier = Preconditions.checkNotNull(textClassifier);
+ mText = Preconditions.checkNotNull(text).toString();
+ mSelectionStart = selectionStart;
+ mSelectionEnd = selectionEnd;
+ }
+
+ @WorkerThread
+ public SelectionResult classifyText() {
+ trimText();
+ return new SelectionResult(
+ mSelectionStart,
+ mSelectionEnd,
+ mTextClassifier.getTextClassificationResult(
+ mTrimmedText, mRelativeStart, mRelativeEnd));
+ }
+
+ @WorkerThread
+ public SelectionResult suggestSelection() {
+ trimText();
+ final TextSelection sel = mTextClassifier.suggestSelection(
+ mTrimmedText, mRelativeStart, mRelativeEnd);
+ mSelectionStart = Math.max(0, sel.getSelectionStartIndex() + mTrimStart);
+ mSelectionEnd = Math.min(mText.length(), sel.getSelectionEndIndex() + mTrimStart);
+ return classifyText();
+ }
+
+ private void trimText() {
+ mTrimStart = Math.max(0, mSelectionStart - TRIM_DELTA);
+ final int referenceEnd = Math.min(mText.length(), mSelectionEnd + TRIM_DELTA);
+ mTrimmedText = mText.subSequence(mTrimStart, referenceEnd);
+ mRelativeStart = mSelectionStart - mTrimStart;
+ mRelativeEnd = mSelectionEnd - mTrimStart;
+ }
+ }
+
+ /**
+ * Selection result.
+ */
+ private static final class SelectionResult {
+ private final int mStart;
+ private final int mEnd;
+ private final TextClassificationResult mResult;
+
+ SelectionResult(int start, int end, TextClassificationResult result) {
+ mStart = start;
+ mEnd = end;
+ mResult = Preconditions.checkNotNull(result);
+ }
+ }
+}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index b18ca45..20e325c 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -113,6 +113,7 @@
import android.text.style.UpdateAppearance;
import android.text.util.Linkify;
import android.util.AttributeSet;
+import android.util.IntArray;
import android.util.Log;
import android.util.TypedValue;
import android.view.AccessibilityIterators.TextSegmentIterator;
@@ -164,6 +165,8 @@
import com.android.internal.util.FastMath;
import com.android.internal.widget.EditableInputConnection;
+import libcore.util.EmptyArray;
+
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
@@ -268,6 +271,7 @@
* @attr ref android.R.styleable#TextView_autoSizeMinTextSize
* @attr ref android.R.styleable#TextView_autoSizeMaxTextSize
* @attr ref android.R.styleable#TextView_autoSizeStepGranularity
+ * @attr ref android.R.styleable#TextView_autoSizeStepSizeSet
*/
@RemoteView
public class TextView extends View implements ViewTreeObserver.OnPreDrawListener {
@@ -715,8 +719,13 @@
private int mAutoSizeMinTextSizeInPx = 0;
// Maximum text size for auto-sizing in pixels.
private int mAutoSizeMaxTextSizeInPx = 0;
- // Contains the sorted set of desired text sizes in pixels to pick from when auto-sizing text.
- private int[] mAutoSizeTextSizesInPx;
+ // Contains a (specified or computed) distinct sorted set of text sizes in pixels to pick from
+ // when auto-sizing text.
+ private int[] mAutoSizeTextSizesInPx = EmptyArray.INT;
+ // Specifies whether auto-size should use the provided auto size steps set or if it should
+ // build the steps set using mAutoSizeMinTextSizeInPx, mAutoSizeMaxTextSizeInPx and
+ // mAutoSizeStepGranularityInPx.
+ private boolean mHasPredefinedAutoSizeSet = false;
// Watcher used to notify changes to auto-fill manager.
private AutoFillChangeWatcher mAutoFillChangeWatcher;
@@ -1308,8 +1317,19 @@
case com.android.internal.R.styleable.TextView_autoSizeMaxTextSize:
mAutoSizeMaxTextSizeInPx = a.getDimensionPixelSize(attr, 0);
break;
+
+ case com.android.internal.R.styleable.TextView_autoSizeStepSizeSet:
+ final int autoSizeStepSizeArrayResId = a.getResourceId(attr, 0);
+ if (autoSizeStepSizeArrayResId > 0) {
+ final TypedArray autoSizePreDefTextSizes = a.getResources()
+ .obtainTypedArray(autoSizeStepSizeArrayResId);
+ setupAutoSizeStepSizeSet(autoSizePreDefTextSizes);
+ autoSizePreDefTextSizes.recycle();
+ }
+ break;
}
}
+
a.recycle();
BufferType bufferType = BufferType.EDITABLE;
@@ -1606,7 +1626,7 @@
mAutoSizeMinTextSizeInPx = 0;
mAutoSizeMaxTextSizeInPx = 0;
mAutoSizeStepGranularityInPx = 0;
- mAutoSizeTextSizesInPx = null;
+ mAutoSizeTextSizesInPx = EmptyArray.INT;
mNeedsAutoSizeText = false;
}
break;
@@ -1658,6 +1678,7 @@
if (supportsAutoSizeText()) {
mAutoSizeStepGranularityInPx = (int) TypedValue.applyDimension(
unit, size, getResources().getDisplayMetrics());
+ mHasPredefinedAutoSizeSet = false;
setupAutoSizeTextXY();
}
}
@@ -1690,6 +1711,7 @@
if (supportsAutoSizeText()) {
mAutoSizeMinTextSizeInPx = (int) TypedValue.applyDimension(
unit, size, getResources().getDisplayMetrics());
+ mHasPredefinedAutoSizeSet = false;
setupAutoSizeTextXY();
}
}
@@ -1723,6 +1745,7 @@
if (supportsAutoSizeText()) {
mAutoSizeMaxTextSizeInPx = (int) TypedValue.applyDimension(
unit, size, getResources().getDisplayMetrics());
+ mHasPredefinedAutoSizeSet = false;
setupAutoSizeTextXY();
}
}
@@ -1737,44 +1760,137 @@
return mAutoSizeMaxTextSizeInPx;
}
+ /**
+ * Sets a predefined array of sizes to be used when auto-sizing.
+ *
+ * <ul>Note:
+ * <li>when <code>presetSizes</code> is not empty then the auto-size algorithm will use the
+ * values provided here instead of calculating the values based on min, max and step size. Also
+ * the values will be de-duplicated, sorted and negative or zero values will be removed.
+ * <li>when <code>presetSizes</code> is empty then the auto-size algorithm will use the min, max
+ * and step size to build the set of available sizes to choose from. Note that if no values have
+ * been provided for any of min, max or step size then defaults will be used.
+ * </ul>
+ *
+ * @param presetSizes an {@code int} array of sizes in pixels
+ *
+ * @attr ref android.R.styleable#TextView_autoSizeStepSizeSet
+ *
+ * @see #getAutoSizeTextPresetSizes()
+ */
+ public void setAutoSizeTextPresetSizes(@NonNull int[] presetSizes) {
+ if (supportsAutoSizeText()) {
+ if (presetSizes.length > 0) {
+ mAutoSizeTextSizesInPx = cleanupAutoSizePredefinedSizes(presetSizes);
+ final int sizesLength = mAutoSizeTextSizesInPx.length;
+ mHasPredefinedAutoSizeSet = sizesLength > 0;
+ if (mHasPredefinedAutoSizeSet) {
+ mAutoSizeMinTextSizeInPx = mAutoSizeTextSizesInPx[0];
+ mAutoSizeMaxTextSizeInPx = mAutoSizeTextSizesInPx[sizesLength - 1];
+ mAutoSizeStepGranularityInPx = 0;
+ }
+ } else {
+ mHasPredefinedAutoSizeSet = false;
+ }
+ setupAutoSizeTextXY();
+ }
+ }
+
+ /**
+ * @return the current auto-size {@code int} sizes array (in pixels).
+ *
+ * @see #setAutoSizeTextPresetSizes(int[])
+ * @see #setAutoSizeMinTextSize(int, float)
+ * @see #setAutoSizeMaxTextSize(int, float)
+ * @see #setAutoSizeStepGranularity(int, float)
+ */
+ public int[] getAutoSizeTextPresetSizes() {
+ return mAutoSizeTextSizesInPx;
+ }
+
+ private void setupAutoSizeStepSizeSet(TypedArray textSizes) {
+ final int textSizesLength = textSizes.length();
+ final int[] parsedSizes = new int[textSizesLength];
+
+ if (textSizesLength > 0) {
+ for (int i = 0; i < textSizesLength; i++) {
+ parsedSizes[i] = textSizes.getDimensionPixelSize(i, -1);
+ }
+ mAutoSizeTextSizesInPx = cleanupAutoSizePredefinedSizes(parsedSizes);
+ mHasPredefinedAutoSizeSet = mAutoSizeTextSizesInPx.length > 0;
+ }
+ }
+
+ // Returns distinct sorted positive values.
+ private int[] cleanupAutoSizePredefinedSizes(int[] predefinedValues) {
+ final int predefinedValuesLength = predefinedValues.length;
+ if (predefinedValuesLength == 0) {
+ return predefinedValues;
+ }
+ Arrays.sort(predefinedValues);
+
+ final IntArray uniqueValidSizes = new IntArray();
+ for (int i = 0; i < predefinedValuesLength; i++) {
+ final int currentPredefinedValue = predefinedValues[i];
+
+ if (currentPredefinedValue > 0
+ && uniqueValidSizes.binarySearch(currentPredefinedValue) < 0) {
+ uniqueValidSizes.add(currentPredefinedValue);
+ }
+ }
+
+ return predefinedValuesLength == uniqueValidSizes.size()
+ ? predefinedValues
+ : uniqueValidSizes.toArray();
+ }
+
private void setupAutoSizeTextXY() {
if (supportsAutoSizeText() && mAutoSizeTextType == AUTO_SIZE_TEXT_TYPE_XY) {
- // Set valid defaults.
- if (mAutoSizeMinTextSizeInPx <= 0) {
- mAutoSizeMinTextSizeInPx = (int) TypedValue.applyDimension(
- TypedValue.COMPLEX_UNIT_SP,
- DEFAULT_AUTO_SIZE_MIN_TEXT_SIZE_IN_SP,
- getResources().getDisplayMetrics());
- }
+ // Calculate the sizes set based on minimum size, maximum size and step size if we do
+ // not have a predefined set of sizes or if the current sizes array is empty.
+ if (!mHasPredefinedAutoSizeSet || mAutoSizeTextSizesInPx.length == 0) {
+ // Set valid defaults.
+ if (mAutoSizeMinTextSizeInPx <= 0) {
+ mAutoSizeMinTextSizeInPx = (int) TypedValue.applyDimension(
+ TypedValue.COMPLEX_UNIT_SP,
+ DEFAULT_AUTO_SIZE_MIN_TEXT_SIZE_IN_SP,
+ getResources().getDisplayMetrics());
+ }
- if (mAutoSizeMaxTextSizeInPx <= 0) {
- mAutoSizeMaxTextSizeInPx = (int) TypedValue.applyDimension(
- TypedValue.COMPLEX_UNIT_SP,
- DEFAULT_AUTO_SIZE_MAX_TEXT_SIZE_IN_SP,
- getResources().getDisplayMetrics());
- }
+ if (mAutoSizeMaxTextSizeInPx <= 0) {
+ mAutoSizeMaxTextSizeInPx = (int) TypedValue.applyDimension(
+ TypedValue.COMPLEX_UNIT_SP,
+ DEFAULT_AUTO_SIZE_MAX_TEXT_SIZE_IN_SP,
+ getResources().getDisplayMetrics());
+ }
- if (mAutoSizeStepGranularityInPx <= 0) {
- mAutoSizeStepGranularityInPx = DEFAULT_AUTO_SIZE_GRANULARITY_IN_PX;
- }
+ if (mAutoSizeStepGranularityInPx <= 0) {
+ mAutoSizeStepGranularityInPx = DEFAULT_AUTO_SIZE_GRANULARITY_IN_PX;
+ }
- // Validate.
- if (mAutoSizeMaxTextSizeInPx <= mAutoSizeMinTextSizeInPx) {
- throw new IllegalStateException("Maximum auto-size text size ("
- + mAutoSizeMaxTextSizeInPx + "px) is less or equal to minimum auto-size "
- + "text size (" + mAutoSizeMinTextSizeInPx + "px)");
- }
+ // Validate.
+ if (mAutoSizeMaxTextSizeInPx <= mAutoSizeMinTextSizeInPx) {
+ throw new IllegalStateException("Maximum auto-size text size ("
+ + mAutoSizeMaxTextSizeInPx
+ + "px) is less or equal to minimum auto-size "
+ + "text size (" + mAutoSizeMinTextSizeInPx + "px)");
+ }
- // Calculate sizes to choose from based on the current auto-size configuration.
- final int autoSizeValuesLength = (int) Math.ceil(
- (mAutoSizeMaxTextSizeInPx - mAutoSizeMinTextSizeInPx)
- / mAutoSizeStepGranularityInPx);
-
- mAutoSizeTextSizesInPx = new int[autoSizeValuesLength];
- int sizeToAdd = mAutoSizeMinTextSizeInPx;
- for (int i = 0; i < autoSizeValuesLength; i++) {
- mAutoSizeTextSizesInPx[i] = sizeToAdd;
- sizeToAdd += mAutoSizeStepGranularityInPx;
+ // Calculate sizes to choose from based on the current auto-size configuration.
+ int autoSizeValuesLength = (int) Math.ceil(
+ (mAutoSizeMaxTextSizeInPx - mAutoSizeMinTextSizeInPx)
+ / (float) mAutoSizeStepGranularityInPx);
+ // Also reserve a slot for the max size if it fits.
+ if ((mAutoSizeMaxTextSizeInPx - mAutoSizeMinTextSizeInPx)
+ % mAutoSizeStepGranularityInPx == 0) {
+ autoSizeValuesLength++;
+ }
+ mAutoSizeTextSizesInPx = new int[autoSizeValuesLength];
+ int sizeToAdd = mAutoSizeMinTextSizeInPx;
+ for (int i = 0; i < autoSizeValuesLength; i++) {
+ mAutoSizeTextSizesInPx[i] = sizeToAdd;
+ sizeToAdd += mAutoSizeStepGranularityInPx;
+ }
}
mNeedsAutoSizeText = true;
@@ -6642,7 +6758,7 @@
*/
public boolean handleBackInTextActionModeIfNeeded(KeyEvent event) {
// Do nothing unless mEditor is in text action mode.
- if (mEditor == null || mEditor.mTextActionMode == null) {
+ if (mEditor == null || mEditor.getTextActionMode() == null) {
return false;
}
@@ -6826,7 +6942,7 @@
// Has to be done on key down (and not on key up) to correctly be intercepted.
case KeyEvent.KEYCODE_BACK:
- if (mEditor != null && mEditor.mTextActionMode != null) {
+ if (mEditor != null && mEditor.getTextActionMode() != null) {
stopTextActionMode();
return KEY_EVENT_HANDLED;
}
@@ -7822,16 +7938,6 @@
scrollTo(0, 0);
}
- if (isAutoSizeEnabled()) {
- if (mNeedsAutoSizeText) {
- // Call auto-size after the width and height have been calculated.
- autoSizeText();
- }
- // Always try to auto-size if enabled. Functions that do not want to trigger auto-sizing
- // after the next measuring round should set this to false.
- mNeedsAutoSizeText = true;
- }
-
setMeasuredDimension(width, height);
}
@@ -7839,8 +7945,8 @@
* Automatically computes and sets the text size.
*/
private void autoSizeText() {
- final int maxWidth = getMeasuredWidth() - getTotalPaddingLeft() - getTotalPaddingRight();
- final int maxHeight = getMeasuredHeight() - getTotalPaddingBottom() - getTotalPaddingTop();
+ final int maxWidth = getWidth() - getTotalPaddingLeft() - getTotalPaddingRight();
+ final int maxHeight = getHeight() - getExtendedPaddingBottom() - getExtendedPaddingTop();
if (maxWidth <= 0 || maxHeight <= 0) {
return;
@@ -7914,11 +8020,6 @@
return false;
}
- // Width overflow.
- if (layout.getWidth() > availableSpace.right) {
- return false;
- }
-
// Height overflow.
if (layout.getHeight() > availableSpace.bottom) {
return false;
@@ -8086,6 +8187,16 @@
mDeferScroll = -1;
bringPointIntoView(Math.min(curs, mText.length()));
}
+
+ if (isAutoSizeEnabled()) {
+ if (mNeedsAutoSizeText) {
+ // Call auto-size after the width and height have been calculated.
+ autoSizeText();
+ }
+ // Always try to auto-size if enabled. Functions that do not want to trigger auto-sizing
+ // after the next layout round should set this to false.
+ mNeedsAutoSizeText = true;
+ }
}
private boolean isShowingHint() {
@@ -9019,7 +9130,8 @@
if (mEditor != null) {
mEditor.refreshTextActionMode();
- if (!hasSelection() && mEditor.mTextActionMode == null && hasTransientState()) {
+ if (!hasSelection()
+ && mEditor.getTextActionMode() == null && hasTransientState()) {
// User generated selection has been removed.
setHasTransientState(false);
}
@@ -10166,7 +10278,7 @@
Selection.setSelection((Spannable) text, start, end);
// Make sure selection mode is engaged.
if (mEditor != null) {
- mEditor.startSelectionActionMode(null);
+ mEditor.startSelectionActionModeAsync();
}
return true;
}
diff --git a/core/java/com/android/internal/textservice/ISpellCheckerService.aidl b/core/java/com/android/internal/textservice/ISpellCheckerService.aidl
index 67d7b3e..6a259645 100644
--- a/core/java/com/android/internal/textservice/ISpellCheckerService.aidl
+++ b/core/java/com/android/internal/textservice/ISpellCheckerService.aidl
@@ -16,16 +16,32 @@
package com.android.internal.textservice;
+import com.android.internal.textservice.ISpellCheckerServiceCallback;
import com.android.internal.textservice.ISpellCheckerSession;
import com.android.internal.textservice.ISpellCheckerSessionListener;
import android.os.Bundle;
/**
- * Public interface to the global spell checker.
+ * IPC channels from TextServicesManagerService to SpellCheckerService.
* @hide
*/
-interface ISpellCheckerService {
- ISpellCheckerSession getISpellCheckerSession(
- String locale, ISpellCheckerSessionListener listener, in Bundle bundle);
+oneway interface ISpellCheckerService {
+ /**
+ * Called from the system when an application is requesting a new spell checker session.
+ *
+ * <p>Note: This is an internal protocol used by the system to establish spell checker sessions,
+ * which is not guaranteed to be stable and is subject to change.</p>
+ *
+ * @param locale locale to be returned from
+ * {@link android.service.textservice.SpellCheckerService.Session#getLocale()}
+ * @param listener IPC channel object to be used to implement
+ * {@link android.service.textservice.SpellCheckerService.Session#onGetSuggestionsMultiple(TextInfo[], int, boolean)} and
+ * {@link android.service.textservice.SpellCheckerService.Session#onGetSuggestions(TextInfo, int)}
+ * @param bundle bundle to be returned from {@link android.service.textservice.SpellCheckerService.Session#getBundle()}
+ * @param callback IPC channel to return the result to the caller in an asynchronous manner
+ */
+ void getISpellCheckerSession(
+ String locale, ISpellCheckerSessionListener listener, in Bundle bundle,
+ ISpellCheckerServiceCallback callback);
}
diff --git a/core/java/com/android/internal/textservice/ISpellCheckerServiceCallback.aidl b/core/java/com/android/internal/textservice/ISpellCheckerServiceCallback.aidl
new file mode 100644
index 0000000..e716cc1
--- /dev/null
+++ b/core/java/com/android/internal/textservice/ISpellCheckerServiceCallback.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.textservice;
+
+import com.android.internal.textservice.ISpellCheckerSession;
+import com.android.internal.textservice.ISpellCheckerSessionListener;
+
+import android.os.Bundle;
+
+/**
+ * IPC channels from SpellCheckerService to TextServicesManagerService.
+ * @hide
+ */
+oneway interface ISpellCheckerServiceCallback {
+ // TODO: Currently SpellCheckerSession just ignores null newSession and continues waiting for
+ // the next onSessionCreated with non-null newSession, which is supposed to never happen if
+ // the system is working normally. We should at least free up resources in SpellCheckerSession.
+ // Note: This method is called from non-system processes, in theory we cannot assume that
+ // this method is always be called only once with non-null value.
+ void onSessionCreated(ISpellCheckerSession newSession);
+}
diff --git a/core/java/com/android/internal/textservice/ITextServicesSessionListener.aidl b/core/java/com/android/internal/textservice/ITextServicesSessionListener.aidl
index ecb6cd0..08d2a5d 100644
--- a/core/java/com/android/internal/textservice/ITextServicesSessionListener.aidl
+++ b/core/java/com/android/internal/textservice/ITextServicesSessionListener.aidl
@@ -21,7 +21,7 @@
import android.view.textservice.SpellCheckerInfo;
/**
- * Interface to the text service session.
+ * (Per-session) IPC channels from TextServicesManagerService to spell checker client applications.
* @hide
*/
interface ITextServicesSessionListener {
diff --git a/core/java/com/android/internal/util/MessageUtils.java b/core/java/com/android/internal/util/MessageUtils.java
index 184245e..e733c30a 100644
--- a/core/java/com/android/internal/util/MessageUtils.java
+++ b/core/java/com/android/internal/util/MessageUtils.java
@@ -42,10 +42,11 @@
/**
* Finds the names of integer constants. Searches the specified {@code classes}, looking for
- * accessible static integer fields whose names begin with one of the specified {@prefixes}.
+ * accessible static integer fields whose names begin with one of the specified
+ * {@code prefixes}.
*
* @param classes the classes to examine.
- * @prefixes only consider fields names starting with one of these prefixes.
+ * @param prefixes only consider fields names starting with one of these prefixes.
* @return a {@link SparseArray} mapping integer constants to their names.
*/
public static SparseArray<String> findMessageNames(Class[] classes, String[] prefixes) {
@@ -122,7 +123,6 @@
* accessible static integer values whose names begin with {@link #DEFAULT_PREFIXES}.
*
* @param classNames the classes to examine.
- * @prefixes only consider fields names starting with one of these prefixes.
* @return a {@link SparseArray} mapping integer constants to their names.
*/
public static SparseArray<String> findMessageNames(Class[] classNames) {
diff --git a/core/java/com/android/internal/view/InputMethodClient.java b/core/java/com/android/internal/view/InputMethodClient.java
index c27e9aa..802ce3e 100644
--- a/core/java/com/android/internal/view/InputMethodClient.java
+++ b/core/java/com/android/internal/view/InputMethodClient.java
@@ -32,13 +32,14 @@
public static final int START_INPUT_REASON_UNBOUND_FROM_IMMS = 6;
public static final int START_INPUT_REASON_ACTIVATED_BY_IMMS = 7;
public static final int START_INPUT_REASON_DEACTIVATED_BY_IMMS = 8;
+ public static final int START_INPUT_REASON_SESSION_CREATED_BY_IME = 9;
@Retention(SOURCE)
@IntDef({START_INPUT_REASON_UNSPECIFIED, START_INPUT_REASON_WINDOW_FOCUS_GAIN,
START_INPUT_REASON_WINDOW_FOCUS_GAIN_REPORT_ONLY,
START_INPUT_REASON_APP_CALLED_RESTART_INPUT_API, START_INPUT_REASON_CHECK_FOCUS,
START_INPUT_REASON_BOUND_TO_IMMS, START_INPUT_REASON_ACTIVATED_BY_IMMS,
- START_INPUT_REASON_DEACTIVATED_BY_IMMS})
+ START_INPUT_REASON_DEACTIVATED_BY_IMMS, START_INPUT_REASON_SESSION_CREATED_BY_IME})
public @interface StartInputReason {}
public static String getStartInputReason(@StartInputReason final int reason) {
@@ -61,6 +62,8 @@
return "ACTIVATED_BY_IMMS";
case START_INPUT_REASON_DEACTIVATED_BY_IMMS:
return "DEACTIVATED_BY_IMMS";
+ case START_INPUT_REASON_SESSION_CREATED_BY_IME:
+ return "SESSION_CREATED_BY_IME";
default:
return "Unknown=" + reason;
}
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index 58e694a..854d013 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -32,6 +32,7 @@
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.util.Size;
+import android.util.TypedValue;
import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -1113,6 +1114,7 @@
mMainPanel.removeAllViews();
mMainPanel.setPaddingRelative(0, 0, 0, 0);
+ int lastGroupId = -1;
boolean isFirstItem = true;
while (!remainingMenuItems.isEmpty()) {
final MenuItem menuItem = remainingMenuItems.peek();
@@ -1125,11 +1127,11 @@
menuItemButton.getPaddingTop(),
menuItemButton.getPaddingEnd(),
menuItemButton.getPaddingBottom());
- isFirstItem = false;
}
// Adding additional end padding for the last button to even out button spacing.
- if (remainingMenuItems.size() == 1) {
+ boolean isLastItem = remainingMenuItems.size() == 1;
+ if (isLastItem) {
menuItemButton.setPaddingRelative(
menuItemButton.getPaddingStart(),
menuItemButton.getPaddingTop(),
@@ -1138,25 +1140,64 @@
}
menuItemButton.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
- int menuItemButtonWidth = Math.min(menuItemButton.getMeasuredWidth(), toolbarWidth);
+ final int menuItemButtonWidth = Math.min(menuItemButton.getMeasuredWidth(), toolbarWidth);
+
+ final boolean isNewGroup = !isFirstItem && lastGroupId != menuItem.getGroupId();
+ final int extraPadding = isNewGroup ? menuItemButton.getPaddingEnd() * 2 : 0;
+
// Check if we can fit an item while reserving space for the overflowButton.
boolean canFitWithOverflow =
- menuItemButtonWidth <= availableWidth - mOverflowButtonSize.getWidth();
+ menuItemButtonWidth <=
+ availableWidth - mOverflowButtonSize.getWidth() - extraPadding;
boolean canFitNoOverflow =
- remainingMenuItems.size() == 1 && menuItemButtonWidth <= availableWidth;
+ isLastItem && menuItemButtonWidth <= availableWidth - extraPadding;
if (canFitWithOverflow || canFitNoOverflow) {
+ if (isNewGroup) {
+ final View border = createBorder(mContext);
+ final int borderWidth = border.getLayoutParams().width;
+
+ // Add extra padding to the end of the previous button.
+ // Half of the extra padding (less borderWidth) goes to the previous button.
+ View previousButton = mMainPanel.getChildAt(mMainPanel.getChildCount() - 1);
+ final int prevPaddingEnd = previousButton.getPaddingEnd()
+ + extraPadding / 2 - borderWidth;
+ previousButton.setPaddingRelative(
+ previousButton.getPaddingStart(),
+ previousButton.getPaddingTop(),
+ prevPaddingEnd,
+ previousButton.getPaddingBottom());
+ final ViewGroup.LayoutParams prevParams = previousButton.getLayoutParams();
+ prevParams.width += extraPadding / 2 - borderWidth;
+ previousButton.setLayoutParams(prevParams);
+
+ // Add extra padding to the start of this button.
+ // Other half of the extra padding goes to this button.
+ final int paddingStart = menuItemButton.getPaddingStart()
+ + extraPadding / 2;
+ menuItemButton.setPaddingRelative(
+ paddingStart,
+ menuItemButton.getPaddingTop(),
+ menuItemButton.getPaddingEnd(),
+ menuItemButton.getPaddingBottom());
+
+ // Include a border.
+ mMainPanel.addView(border);
+ }
+
setButtonTagAndClickListener(menuItemButton, menuItem);
mMainPanel.addView(menuItemButton);
- ViewGroup.LayoutParams params = menuItemButton.getLayoutParams();
- params.width = menuItemButtonWidth;
+ final ViewGroup.LayoutParams params = menuItemButton.getLayoutParams();
+ params.width = menuItemButtonWidth + extraPadding / 2;
menuItemButton.setLayoutParams(params);
- availableWidth -= menuItemButtonWidth;
+ availableWidth -= menuItemButtonWidth + extraPadding;
remainingMenuItems.pop();
} else {
// Reserve space for overflowButton.
mMainPanel.setPaddingRelative(0, 0, mOverflowButtonSize.getWidth(), 0);
break;
}
+ lastGroupId = menuItem.getGroupId();
+ isFirstItem = false;
}
mMainPanelSize = measure(mMainPanel);
return remainingMenuItems;
@@ -1688,6 +1729,23 @@
return popupWindow;
}
+ private static View createBorder(Context context) {
+ // TODO: Inflate this instead.
+ View border = new View(context);
+ int _1dp = (int) TypedValue.applyDimension(
+ TypedValue.COMPLEX_UNIT_DIP, 1, context.getResources().getDisplayMetrics());
+ LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
+ _1dp, ViewGroup.LayoutParams.MATCH_PARENT);
+ params.setMarginsRelative(0, _1dp * 10, 0, _1dp * 10);
+ border.setLayoutParams(params);
+ border.setBackgroundColor(Color.parseColor("#9E9E9E"));
+ border.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
+ border.setEnabled(false);
+ border.setFocusable(false);
+ border.setContentDescription(null);
+ return border;
+ }
+
/**
* Creates an "appear" animation for the specified view.
*
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 58fb145..ef6e6c2 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -569,11 +569,12 @@
/**
* Clear any lock pattern or password.
*/
- public void clearLock(int userHandle) {
+ public void clearLock(String savedCredential, int userHandle) {
setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userHandle);
- try {
- getLockSettings().setLockCredential(null, CREDENTIAL_TYPE_NONE, null, userHandle);
+ try{
+ getLockSettings().setLockCredential(null, CREDENTIAL_TYPE_NONE, savedCredential,
+ userHandle);
} catch (RemoteException e) {
// well, we tried...
}
@@ -758,7 +759,6 @@
public void saveLockPassword(String password, String savedPassword, int quality,
int userHandle) {
try {
- DevicePolicyManager dpm = getDevicePolicyManager();
if (password == null || password.length() < MIN_LOCK_PASSWORD_SIZE) {
throw new IllegalArgumentException("password must not be null and at least "
+ "of length " + MIN_LOCK_PASSWORD_SIZE);
@@ -769,48 +769,55 @@
getLockSettings().setLockCredential(password, CREDENTIAL_TYPE_PASSWORD, savedPassword,
userHandle);
- // Update the device encryption password.
- if (userHandle == UserHandle.USER_SYSTEM
- && LockPatternUtils.isDeviceEncryptionEnabled()) {
- if (!shouldEncryptWithCredentials(true)) {
- clearEncryptionPassword();
- } else {
- boolean numeric = computedQuality
- == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
- boolean numericComplex = computedQuality
- == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
- int type = numeric || numericComplex ? StorageManager.CRYPT_TYPE_PIN
- : StorageManager.CRYPT_TYPE_PASSWORD;
- updateEncryptionPassword(type, password);
- }
- }
-
- // Add the password to the password history. We assume all
- // password hashes have the same length for simplicity of implementation.
- String passwordHistory = getString(PASSWORD_HISTORY_KEY, userHandle);
- if (passwordHistory == null) {
- passwordHistory = "";
- }
- int passwordHistoryLength = getRequestedPasswordHistoryLength(userHandle);
- if (passwordHistoryLength == 0) {
- passwordHistory = "";
- } else {
- byte[] hash = passwordToHash(password, userHandle);
- passwordHistory = new String(hash, StandardCharsets.UTF_8) + "," + passwordHistory;
- // Cut it to contain passwordHistoryLength hashes
- // and passwordHistoryLength -1 commas.
- passwordHistory = passwordHistory.substring(0, Math.min(hash.length
- * passwordHistoryLength + passwordHistoryLength - 1, passwordHistory
- .length()));
- }
- setString(PASSWORD_HISTORY_KEY, passwordHistory, userHandle);
- onAfterChangingPassword(userHandle);
+ addEncryptionPassword(password, computedQuality, userHandle);
+ updatePasswordHistory(password, userHandle);
} catch (RemoteException re) {
// Cant do much
Log.e(TAG, "Unable to save lock password " + re);
}
}
+ private void addEncryptionPassword(String password, int quality, int userHandle) {
+ // Update the device encryption password.
+ if (userHandle == UserHandle.USER_SYSTEM
+ && LockPatternUtils.isDeviceEncryptionEnabled()) {
+ if (!shouldEncryptWithCredentials(true)) {
+ clearEncryptionPassword();
+ } else {
+ boolean numeric = quality == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
+ boolean numericComplex = quality
+ == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
+ int type = numeric || numericComplex ? StorageManager.CRYPT_TYPE_PIN
+ : StorageManager.CRYPT_TYPE_PASSWORD;
+ updateEncryptionPassword(type, password);
+ }
+ }
+ }
+
+ private void updatePasswordHistory(String password, int userHandle) {
+
+ // Add the password to the password history. We assume all
+ // password hashes have the same length for simplicity of implementation.
+ String passwordHistory = getString(PASSWORD_HISTORY_KEY, userHandle);
+ if (passwordHistory == null) {
+ passwordHistory = "";
+ }
+ int passwordHistoryLength = getRequestedPasswordHistoryLength(userHandle);
+ if (passwordHistoryLength == 0) {
+ passwordHistory = "";
+ } else {
+ byte[] hash = passwordToHash(password, userHandle);
+ passwordHistory = new String(hash, StandardCharsets.UTF_8) + "," + passwordHistory;
+ // Cut it to contain passwordHistoryLength hashes
+ // and passwordHistoryLength -1 commas.
+ passwordHistory = passwordHistory.substring(0, Math.min(hash.length
+ * passwordHistoryLength + passwordHistoryLength - 1, passwordHistory
+ .length()));
+ }
+ setString(PASSWORD_HISTORY_KEY, passwordHistory, userHandle);
+ onAfterChangingPassword(userHandle);
+ }
+
/**
* Determine if the device supports encryption, even if it's set to default. This
* differs from isDeviceEncrypted() in that it returns true even if the device is
diff --git a/core/java/com/android/internal/widget/WatchHeaderListView.java b/core/java/com/android/internal/widget/WatchHeaderListView.java
index 4fd19c3..7e91537 100644
--- a/core/java/com/android/internal/widget/WatchHeaderListView.java
+++ b/core/java/com/android/internal/widget/WatchHeaderListView.java
@@ -26,8 +26,7 @@
import android.widget.HeaderViewListAdapter;
import java.util.ArrayList;
-
-import com.android.internal.util.Predicate;
+import java.util.function.Predicate;
public class WatchHeaderListView extends ListView {
private View mTopPanel;
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index be3a87b..eaf9e91 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -1006,9 +1006,8 @@
ALOGD("Native heap dump complete.\n");
}
-
-static void android_os_Debug_dumpNativeBacktraceToFile(JNIEnv* env, jobject clazz,
- jint pid, jstring fileName)
+static void android_os_Debug_dumpNativeBacktraceToFileTimeout(JNIEnv* env, jobject clazz,
+ jint pid, jstring fileName, jint timeoutSecs)
{
if (fileName == NULL) {
jniThrowNullPointerException(env, "file == null");
@@ -1031,7 +1030,7 @@
if (lseek(fd, 0, SEEK_END) < 0) {
fprintf(stderr, "lseek: %s\n", strerror(errno));
} else {
- dump_backtrace_to_file(pid, fd);
+ dump_backtrace_to_file_timeout(pid, fd, timeoutSecs);
}
close(fd);
@@ -1077,8 +1076,8 @@
(void*)android_os_Debug_getProxyObjectCount },
{ "getBinderDeathObjectCount", "()I",
(void*)android_os_Debug_getDeathObjectCount },
- { "dumpNativeBacktraceToFile", "(ILjava/lang/String;)V",
- (void*)android_os_Debug_dumpNativeBacktraceToFile },
+ { "dumpNativeBacktraceToFileTimeout", "(ILjava/lang/String;I)V",
+ (void*)android_os_Debug_dumpNativeBacktraceToFileTimeout },
{ "getUnreachableMemory", "(IZ)Ljava/lang/String;",
(void*)android_os_Debug_getUnreachableMemory },
};
diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp
index 905a85a..399dec8 100644
--- a/core/jni/android_os_GraphicsEnvironment.cpp
+++ b/core/jni/android_os_GraphicsEnvironment.cpp
@@ -16,7 +16,7 @@
#define LOG_TAG "GraphicsEnvironment"
-#include <gui/GraphicsEnv.h>
+#include <ui/GraphicsEnv.h>
#include <nativehelper/ScopedUtfChars.h>
#include "core_jni_helpers.h"
diff --git a/core/jni/android_os_seccomp.cpp b/core/jni/android_os_seccomp.cpp
index 02c0c62..3f021ae 100644
--- a/core/jni/android_os_seccomp.cpp
+++ b/core/jni/android_os_seccomp.cpp
@@ -216,6 +216,9 @@
AllowSyscall(f, 8); // __NR_creat
AllowSyscall(f, 10); // __NR_unlink
+ // b/35059702
+ AllowSyscall(f, 196); // __NR_lstat64
+
Trap(f);
return install_filter(f);
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 9beae08..ba1d664 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -23,6 +23,7 @@
import "frameworks/base/core/proto/android/service/appwidget.proto";
import "frameworks/base/core/proto/android/service/fingerprint.proto";
import "frameworks/base/core/proto/android/service/netstats.proto";
+import "frameworks/base/core/proto/android/service/notification.proto";
import "frameworks/base/core/proto/android/providers/settings.proto";
package android.os;
@@ -55,4 +56,5 @@
android.service.NetworkStatsServiceDumpProto netstats = 3001;
android.providers.settings.SettingsServiceDumpProto settings = 3002;
android.service.appwidget.AppWidgetServiceDumpProto appwidget = 3003;
+ android.service.notification.NotificationServiceDumpProto notification = 3004;
}
diff --git a/core/proto/android/service/notification.proto b/core/proto/android/service/notification.proto
new file mode 100644
index 0000000..bc257e04
--- /dev/null
+++ b/core/proto/android/service/notification.proto
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+syntax = "proto3";
+
+package android.service.notification;
+
+option java_multiple_files = true;
+option java_outer_classname = "NotificationServiceProto";
+
+message NotificationServiceDumpProto {
+ repeated NotificationRecordProto records = 1;
+}
+
+message NotificationRecordProto {
+ string key = 1;
+ State state = 2;
+ int32 flags = 3;
+ string channelId = 4;
+ string sound = 5;
+ int32 sound_usage = 6;
+ bool can_vibrate = 7;
+ bool can_show_light = 8;
+ string group_key = 9;
+ int32 importance = 10;
+}
+
+enum State {
+ ENQUEUED = 0;
+
+ POSTED = 1;
+}
\ No newline at end of file
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 9824051..640e74d 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -461,12 +461,12 @@
<dimen name="floating_toolbar_height">48dp</dimen>
<dimen name="floating_toolbar_menu_image_button_width">56dp</dimen>
<dimen name="floating_toolbar_menu_image_button_vertical_padding">12dp</dimen>
- <dimen name="floating_toolbar_menu_button_side_padding">16dp</dimen>
+ <dimen name="floating_toolbar_menu_button_side_padding">11dp</dimen>
<dimen name="floating_toolbar_overflow_image_button_width">60dp</dimen>
<dimen name="floating_toolbar_overflow_side_padding">18dp</dimen>
<dimen name="floating_toolbar_text_size">14sp</dimen>
<dimen name="floating_toolbar_menu_button_minimum_width">48dp</dimen>
- <dimen name="floating_toolbar_preferred_width">328dp</dimen>
+ <dimen name="floating_toolbar_preferred_width">400dp</dimen>
<dimen name="floating_toolbar_minimum_overflow_height">96dp</dimen>
<dimen name="floating_toolbar_maximum_overflow_height">192dp</dimen>
<dimen name="floating_toolbar_horizontal_margin">16dp</dimen>
@@ -517,6 +517,7 @@
<dimen name="item_touch_helper_swipe_escape_max_velocity">800dp</dimen>
<!-- The elevation of AutoFill fill window-->
- <dimen name="autofill_fill_elevation">2dp</dimen>
+ <dimen name="autofill_fill_elevation">4dp</dimen>
<dimen name="autofill_fill_item_height">64dp</dimen>
+ <dimen name="autofill_fill_min_margin">16dp</dimen>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 8f3ba87..89269aa 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2835,6 +2835,7 @@
<!-- com.android.server.autofill -->
<java-symbol type="dimen" name="autofill_fill_elevation" />
<java-symbol type="dimen" name="autofill_fill_item_height" />
+ <java-symbol type="dimen" name="autofill_fill_min_margin" />
<java-symbol type="layout" name="autofill_save"/>
<java-symbol type="id" name="autofill_save_title" />
<java-symbol type="id" name="autofill_save_no" />
diff --git a/core/tests/coretests/Android.mk b/core/tests/coretests/Android.mk
index a0a9e01..48b78d4 100644
--- a/core/tests/coretests/Android.mk
+++ b/core/tests/coretests/Android.mk
@@ -34,7 +34,8 @@
espresso-core \
ub-uiautomator \
platform-test-annotations \
- compatibility-device-util
+ compatibility-device-util \
+ truth-prebuilt
LOCAL_JAVA_LIBRARIES := android.test.runner conscrypt telephony-common org.apache.http.legacy
LOCAL_PACKAGE_NAME := FrameworksCoreTests
diff --git a/core/tests/coretests/src/android/app/usage/UsageStatsTest.java b/core/tests/coretests/src/android/app/usage/UsageStatsTest.java
new file mode 100644
index 0000000..c6d077d
--- /dev/null
+++ b/core/tests/coretests/src/android/app/usage/UsageStatsTest.java
@@ -0,0 +1,105 @@
+/*
+ * 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.app.usage;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class UsageStatsTest {
+ private UsageStats left;
+ private UsageStats right;
+
+ @Before
+ public void setUp() throws Exception {
+ left = new UsageStats();
+ right = new UsageStats();
+ }
+
+ @Test
+ public void testEarlierBeginTimeTakesPriorityOnAdd() {
+ left.mPackageName = "com.test";
+ left.mBeginTimeStamp = 100000;
+ right.mPackageName = "com.test";
+ right.mBeginTimeStamp = 99999;
+
+ left.add(right);
+
+ assertThat(left.getFirstTimeStamp()).isEqualTo(99999);
+ }
+
+ @Test
+ public void testLaterEndTimeTakesPriorityOnAdd() {
+ left.mPackageName = "com.test";
+ left.mEndTimeStamp = 100000;
+ right.mPackageName = "com.test";
+ right.mEndTimeStamp = 100001;
+
+ left.add(right);
+
+ assertThat(left.getLastTimeStamp()).isEqualTo(100001);
+ }
+
+ @Test
+ public void testLastUsedTimeIsOverriddenByLaterStats() {
+ left.mPackageName = "com.test";
+ left.mBeginTimeStamp = 100000;
+ left.mLastTimeUsed = 200000;
+ right.mPackageName = "com.test";
+ right.mBeginTimeStamp = 100001;
+ right.mLastTimeUsed = 200001;
+
+ left.add(right);
+
+ assertThat(left.getLastTimeUsed()).isEqualTo(200001);
+ }
+
+ @Test
+ public void testLastUsedTimeIsNotOverriddenByLaterStatsIfUseIsEarlier() {
+ left.mPackageName = "com.test";
+ left.mBeginTimeStamp = 100000;
+ left.mLastTimeUsed = 200000;
+ right.mPackageName = "com.test";
+ right.mBeginTimeStamp = 100001;
+ right.mLastTimeUsed = 150000;
+
+ left.add(right);
+
+ assertThat(left.getLastTimeUsed()).isEqualTo(200000);
+ }
+
+ @Test
+ public void testForegroundTimeIsSummed() {
+ left.mPackageName = "com.test";
+ left.mBeginTimeStamp = 100000;
+ left.mTotalTimeInForeground = 10;
+ right.mPackageName = "com.test";
+ right.mBeginTimeStamp = 100001;
+ right.mTotalTimeInForeground = 1;
+
+ left.add(right);
+
+ assertThat(left.getTotalTimeInForeground()).isEqualTo(11);
+ }
+}
diff --git a/data/etc/framework-sysconfig.xml b/data/etc/framework-sysconfig.xml
index 62ef25b..7fafef7 100644
--- a/data/etc/framework-sysconfig.xml
+++ b/data/etc/framework-sysconfig.xml
@@ -23,4 +23,9 @@
<allow-implicit-broadcast action="android.intent.action.PACKAGE_CHANGED" />
<allow-implicit-broadcast action="android.intent.action.MEDIA_SCANNER_SCAN_FILE" />
+ <!-- Whitelist of what components are permitted as backup data transports. The
+ 'service' attribute here is a flattened ComponentName string. -->
+ <backup-transport-whitelisted-service
+ service="android/com.android.internal.backup.LocalTransportService" />
+
</config>
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index ecf6bd4..e764034 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -36,6 +36,7 @@
"misc.cpp",
"ObbFile.cpp",
"ResourceTypes.cpp",
+ "ResourceUtils.cpp",
"StreamingZipInflater.cpp",
"TypeWrappers.cpp",
"Util.cpp",
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index 542a125..ef0c967 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -31,6 +31,8 @@
#endif
#endif
+#include "androidfw/ResourceUtils.h"
+
namespace android {
AssetManager2::AssetManager2() { memset(&configuration_, 0, sizeof(configuration_)); }
@@ -235,9 +237,9 @@
desired_config = &density_override_config;
}
- const uint32_t package_id = util::get_package_id(resid);
- const uint8_t type_id = util::get_type_id(resid);
- const uint16_t entry_id = util::get_entry_id(resid);
+ const uint32_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 (type_id == 0) {
LOG(ERROR) << base::StringPrintf("Invalid ID 0x%08x.", resid);
@@ -452,7 +454,7 @@
ResolvedBag::Entry* new_entry = new_bag->entries;
for (; map_entry != map_entry_end; ++map_entry) {
uint32_t new_key = dtohl(map_entry->name.ident);
- if (!util::is_internal_resid(new_key)) {
+ if (!is_internal_resid(new_key)) {
// 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) {
@@ -501,7 +503,7 @@
// The keys are expected to be in sorted order. Merge the two bags.
while (map_entry != map_entry_end && parent_entry != parent_entry_end) {
uint32_t child_key = dtohl(map_entry->name.ident);
- if (!util::is_internal_resid(child_key)) {
+ 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);
return nullptr;
@@ -533,7 +535,7 @@
// Finish the child entries if they exist.
while (map_entry != map_entry_end) {
uint32_t new_key = dtohl(map_entry->name.ident);
- if (!util::is_internal_resid(new_key)) {
+ 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);
return nullptr;
@@ -571,12 +573,71 @@
return result;
}
+static bool Utf8ToUtf16(const StringPiece& str, std::u16string* out) {
+ ssize_t len =
+ utf8_to_utf16_length(reinterpret_cast<const uint8_t*>(str.data()), str.size(), false);
+ if (len < 0) {
+ return false;
+ }
+ out->resize(static_cast<size_t>(len));
+ utf8_to_utf16(reinterpret_cast<const uint8_t*>(str.data()), str.size(), &*out->begin(),
+ static_cast<size_t>(len + 1));
+ return true;
+}
+
uint32_t AssetManager2::GetResourceId(const std::string& resource_name,
const std::string& fallback_type,
const std::string& fallback_package) {
- (void)resource_name;
- (void)fallback_type;
- (void)fallback_package;
+ StringPiece package_name, type, entry;
+ if (!ExtractResourceName(resource_name, &package_name, &type, &entry)) {
+ return 0u;
+ }
+
+ if (entry.empty()) {
+ return 0u;
+ }
+
+ if (package_name.empty()) {
+ package_name = fallback_package;
+ }
+
+ if (type.empty()) {
+ type = fallback_type;
+ }
+
+ std::u16string type16;
+ if (!Utf8ToUtf16(type, &type16)) {
+ return 0u;
+ }
+
+ std::u16string entry16;
+ if (!Utf8ToUtf16(entry, &entry16)) {
+ return 0u;
+ }
+
+ const StringPiece16 kAttr16 = u"attr";
+ const static std::u16string kAttrPrivate16 = u"^attr-private";
+
+ for (const PackageGroup& package_group : package_groups_) {
+ for (const LoadedPackage* package : package_group.packages_) {
+ if (package_name != package->GetPackageName()) {
+ // All packages in the same group are expected to have the same package name.
+ break;
+ }
+
+ uint32_t resid = package->FindEntryByName(type16, entry16);
+ if (resid == 0u && kAttr16 == type16) {
+ // Private attributes in libraries (such as the framework) are sometimes encoded
+ // under the type '^attr-private' in order to leave the ID space of public 'attr'
+ // free for future additions. Check '^attr-private' for the same name.
+ resid = package->FindEntryByName(kAttrPrivate16, entry16);
+ }
+
+ if (resid != 0u) {
+ return fix_package_id(resid, package_group.dynamic_ref_table.mAssignedPackageId);
+ }
+ }
+ }
return 0u;
}
@@ -619,15 +680,15 @@
// If the resource ID passed in is not a style, the key can be
// some other identifier that is not a resource ID.
- if (!util::is_valid_resid(attr_resid)) {
+ if (!is_valid_resid(attr_resid)) {
return false;
}
- const uint32_t package_idx = util::get_package_id(attr_resid);
+ const uint32_t package_idx = get_package_id(attr_resid);
// The type ID is 1-based, so subtract 1 to get an index.
- const uint32_t type_idx = util::get_type_id(attr_resid) - 1;
- const uint32_t entry_idx = util::get_entry_id(attr_resid);
+ const uint32_t type_idx = get_type_id(attr_resid) - 1;
+ const uint32_t entry_idx = get_entry_id(attr_resid);
std::unique_ptr<Package>& package = packages_[package_idx];
if (package == nullptr) {
@@ -656,9 +717,9 @@
// and populate the structures.
for (auto bag_iter = begin(bag); bag_iter != bag_iter_end; ++bag_iter) {
const uint32_t attr_resid = bag_iter->key;
- const uint32_t package_idx = util::get_package_id(attr_resid);
- const uint32_t type_idx = util::get_type_id(attr_resid) - 1;
- const uint32_t entry_idx = util::get_entry_id(attr_resid);
+ const uint32_t package_idx = get_package_id(attr_resid);
+ const uint32_t type_idx = get_type_id(attr_resid) - 1;
+ const uint32_t entry_idx = get_entry_id(attr_resid);
Package* package = packages_[package_idx].get();
util::unique_cptr<Type>& type = package->types[type_idx];
if (type->entry_count != type->entry_capacity) {
@@ -691,15 +752,15 @@
uint32_t type_spec_flags = 0u;
for (int iterations_left = kMaxIterations; iterations_left > 0; iterations_left--) {
- if (!util::is_valid_resid(resid)) {
+ if (!is_valid_resid(resid)) {
return kInvalidCookie;
}
- const uint32_t package_idx = util::get_package_id(resid);
+ const uint32_t package_idx = get_package_id(resid);
// Type ID is 1-based, subtract 1 to get the index.
- const uint32_t type_idx = util::get_type_id(resid) - 1;
- const uint32_t entry_idx = util::get_entry_id(resid);
+ const uint32_t type_idx = get_type_id(resid) - 1;
+ const uint32_t entry_idx = get_entry_id(resid);
const Package* package = packages_[package_idx].get();
if (package == nullptr) {
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index cb589ec..db72f48 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -34,6 +34,7 @@
#include "androidfw/ByteBucketArray.h"
#include "androidfw/Chunk.h"
+#include "androidfw/ResourceUtils.h"
#include "androidfw/Util.h"
using android::base::StringPrintf;
@@ -181,9 +182,9 @@
LoadedArscEntry* out_entry, ResTable_config* out_selected_config,
uint32_t* out_flags) const {
ATRACE_CALL();
- const uint8_t package_id = util::get_package_id(resid);
- const uint8_t type_id = util::get_type_id(resid);
- const uint16_t entry_id = util::get_entry_id(resid);
+ 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 (type_id == 0) {
LOG(ERROR) << "Invalid ID 0x" << std::hex << resid << std::dec << ".";
@@ -200,7 +201,7 @@
}
const LoadedPackage* LoadedArsc::GetPackageForId(uint32_t resid) const {
- const uint8_t package_id = util::get_package_id(resid);
+ const uint8_t package_id = get_package_id(resid);
for (const auto& loaded_package : packages_) {
if (loaded_package->package_id_ == package_id) {
return loaded_package.get();
@@ -372,6 +373,45 @@
}
}
+uint32_t LoadedPackage::FindEntryByName(const std::u16string& type_name,
+ const std::u16string& entry_name) const {
+ ssize_t type_idx = type_string_pool_.indexOfString(type_name.data(), type_name.size());
+ if (type_idx < 0) {
+ return 0u;
+ }
+
+ ssize_t key_idx = key_string_pool_.indexOfString(entry_name.data(), entry_name.size());
+ if (key_idx < 0) {
+ return 0u;
+ }
+
+ const TypeSpec* type_spec = type_specs_[type_idx].get();
+ if (type_spec == nullptr) {
+ 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);
+ 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));
+ 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);
+ 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).
+ return make_resid(0x00, type_idx + type_id_offset_ + 1, entry_idx);
+ }
+ }
+ }
+ }
+ return 0u;
+}
+
std::unique_ptr<LoadedPackage> LoadedPackage::Load(const Chunk& chunk) {
ATRACE_CALL();
std::unique_ptr<LoadedPackage> loaded_package{new LoadedPackage()};
diff --git a/libs/androidfw/ResourceUtils.cpp b/libs/androidfw/ResourceUtils.cpp
new file mode 100644
index 0000000..1aa6cf6
--- /dev/null
+++ b/libs/androidfw/ResourceUtils.cpp
@@ -0,0 +1,48 @@
+/*
+ * 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 "androidfw/ResourceUtils.h"
+
+namespace android {
+
+bool ExtractResourceName(const StringPiece& str, StringPiece* out_package, StringPiece* out_type,
+ StringPiece* out_entry) {
+ *out_package = "";
+ *out_type = "";
+ bool has_package_separator = false;
+ bool has_type_separator = false;
+ const char* start = str.data();
+ const char* end = start + str.size();
+ const char* current = start;
+ while (current != end) {
+ if (out_type->size() == 0 && *current == '/') {
+ has_type_separator = true;
+ out_type->assign(start, current - start);
+ start = current + 1;
+ } else if (out_package->size() == 0 && *current == ':') {
+ has_package_separator = true;
+ out_package->assign(start, current - start);
+ start = current + 1;
+ }
+ current++;
+ }
+ out_entry->assign(start, end - start);
+
+ return !(has_package_separator && out_package->empty()) &&
+ !(has_type_separator && out_type->empty());
+}
+
+} // namespace android
diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h
index 91a7cb7..f30b158 100644
--- a/libs/androidfw/include/androidfw/LoadedArsc.h
+++ b/libs/androidfw/include/androidfw/LoadedArsc.h
@@ -101,6 +101,13 @@
// 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;
+ // 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.
+ // Returns a partial resource ID, with the package ID left as 0x00. The caller is responsible
+ // for patching the correct package ID to the resource ID.
+ uint32_t FindEntryByName(const std::u16string& type_name, const std::u16string& entry_name) const;
+
private:
DISALLOW_COPY_AND_ASSIGN(LoadedPackage);
diff --git a/libs/androidfw/include/androidfw/ResourceUtils.h b/libs/androidfw/include/androidfw/ResourceUtils.h
new file mode 100644
index 0000000..6bf7c24
--- /dev/null
+++ b/libs/androidfw/include/androidfw/ResourceUtils.h
@@ -0,0 +1,60 @@
+/*
+ * 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_RESOURCEUTILS_H
+#define ANDROIDFW_RESOURCEUTILS_H
+
+#include "androidfw/StringPiece.h"
+
+namespace android {
+
+// Extracts the package, type, and name from a string of the format: [[package:]type/]name
+// Validation must be performed on each extracted piece.
+// Returns false if there was a syntax error.
+bool ExtractResourceName(const StringPiece& str, StringPiece* out_package, StringPiece* out_type,
+ 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);
+}
+
+inline uint8_t get_package_id(uint32_t resid) {
+ return static_cast<uint8_t>((resid >> 24) & 0x000000ffu);
+}
+
+// The type ID is 1-based, so if the returned value is 0 it is invalid.
+inline uint8_t get_type_id(uint32_t resid) {
+ return static_cast<uint8_t>((resid >> 16) & 0x000000ffu);
+}
+
+inline uint16_t get_entry_id(uint32_t resid) { return static_cast<uint16_t>(resid & 0x0000ffffu); }
+
+inline bool is_internal_resid(uint32_t resid) {
+ return (resid & 0xffff0000u) != 0 && (resid & 0x00ff0000u) == 0;
+}
+
+inline bool is_valid_resid(uint32_t resid) {
+ return (resid & 0x00ff0000u) != 0 && (resid & 0xff000000u) != 0;
+}
+
+inline uint32_t make_resid(uint8_t package_id, uint8_t type_id, uint16_t entry_id) {
+ return (static_cast<uint32_t>(package_id) << 24) | (static_cast<uint32_t>(type_id) << 16) |
+ entry_id;
+}
+
+} // namespace android
+
+#endif /* ANDROIDFW_RESOURCEUTILS_H */
diff --git a/libs/androidfw/include/androidfw/StringPiece.h b/libs/androidfw/include/androidfw/StringPiece.h
index c9effd1..8f6824b 100644
--- a/libs/androidfw/include/androidfw/StringPiece.h
+++ b/libs/androidfw/include/androidfw/StringPiece.h
@@ -257,6 +257,16 @@
return data_ + length_;
}
+template <typename TChar>
+inline bool operator==(const TChar* lhs, const BasicStringPiece<TChar>& rhs) {
+ return BasicStringPiece<TChar>(lhs) == rhs;
+}
+
+template <typename TChar>
+inline bool operator!=(const TChar* lhs, const BasicStringPiece<TChar>& rhs) {
+ return BasicStringPiece<TChar>(lhs) != rhs;
+}
+
inline ::std::ostream& operator<<(::std::ostream& out, const BasicStringPiece<char>& str) {
return out.write(str.data(), str.size());
}
diff --git a/libs/androidfw/include/androidfw/Util.h b/libs/androidfw/include/androidfw/Util.h
index 96b42bf..3950cf2 100644
--- a/libs/androidfw/include/androidfw/Util.h
+++ b/libs/androidfw/include/androidfw/Util.h
@@ -106,29 +106,6 @@
pointer ptr_;
};
-inline uint32_t fix_package_id(uint32_t resid, uint8_t package_id) {
- return resid | (static_cast<uint32_t>(package_id) << 24);
-}
-
-inline uint8_t get_package_id(uint32_t resid) {
- return static_cast<uint8_t>((resid >> 24) & 0x000000ffu);
-}
-
-// The type ID is 1-based, so if the returned value is 0 it is invalid.
-inline uint8_t get_type_id(uint32_t resid) {
- return static_cast<uint8_t>((resid >> 16) & 0x000000ffu);
-}
-
-inline uint16_t get_entry_id(uint32_t resid) { return static_cast<uint16_t>(resid & 0x0000ffffu); }
-
-inline bool is_internal_resid(uint32_t resid) {
- return (resid & 0xffff0000u) != 0 && (resid & 0x00ff0000u) == 0;
-}
-
-inline bool is_valid_resid(uint32_t resid) {
- return (resid & 0x00ff0000u) != 0 && (resid & 0xff000000u) != 0;
-}
-
void ReadUtf16StringFromDevice(const uint16_t* src, size_t len, std::string* out);
} // namespace util
diff --git a/libs/androidfw/tests/Android.mk b/libs/androidfw/tests/Android.mk
index 650f813..19527c5 100644
--- a/libs/androidfw/tests/Android.mk
+++ b/libs/androidfw/tests/Android.mk
@@ -32,6 +32,7 @@
ConfigLocale_test.cpp \
Idmap_test.cpp \
LoadedArsc_test.cpp \
+ ResourceUtils_test.cpp \
ResTable_test.cpp \
Split_test.cpp \
StringPiece_test.cpp \
diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp
index 557d8d4..78fbb0f 100644
--- a/libs/androidfw/tests/AssetManager2_test.cpp
+++ b/libs/androidfw/tests/AssetManager2_test.cpp
@@ -20,6 +20,7 @@
#include "android-base/logging.h"
#include "TestHelpers.h"
+#include "androidfw/ResourceUtils.h"
#include "data/appaslib/R.h"
#include "data/basic/R.h"
#include "data/lib_one/R.h"
@@ -194,11 +195,11 @@
ResTable_config selected_config;
uint32_t flags;
ApkAssetsCookie cookie = assetmanager.GetResource(
- util::fix_package_id(appaslib::R::integer::number1, 0x02), false /*may_be_bag*/,
+ fix_package_id(appaslib::R::integer::number1, 0x02), false /*may_be_bag*/,
0u /*density_override*/, &value, &selected_config, &flags);
ASSERT_NE(kInvalidCookie, cookie);
EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
- EXPECT_EQ(util::fix_package_id(appaslib::R::array::integerArray1, 0x02), value.data);
+ EXPECT_EQ(fix_package_id(appaslib::R::array::integerArray1, 0x02), value.data);
}
TEST_F(AssetManager2Test, FindsBagResourceFromSingleApkAssets) {
@@ -238,9 +239,9 @@
// First two attributes come from lib_one.
EXPECT_EQ(1, bag->entries[0].cookie);
- EXPECT_EQ(0x03, util::get_package_id(bag->entries[0].key));
+ EXPECT_EQ(0x03, get_package_id(bag->entries[0].key));
EXPECT_EQ(1, bag->entries[1].cookie);
- EXPECT_EQ(0x03, util::get_package_id(bag->entries[1].key));
+ EXPECT_EQ(0x03, get_package_id(bag->entries[1].key));
}
TEST_F(AssetManager2Test, MergesStylesWithParentFromSingleApkAssets) {
diff --git a/libs/androidfw/tests/ResourceUtils_test.cpp b/libs/androidfw/tests/ResourceUtils_test.cpp
new file mode 100644
index 0000000..b64a884
--- /dev/null
+++ b/libs/androidfw/tests/ResourceUtils_test.cpp
@@ -0,0 +1,49 @@
+/*
+ * 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 "androidfw/ResourceUtils.h"
+
+#include "TestHelpers.h"
+
+namespace android {
+
+TEST(ResourceUtilsTest, ExtractResourceName) {
+ StringPiece package, type, entry;
+ ASSERT_TRUE(ExtractResourceName("android:string/foo", &package, &type, &entry));
+ EXPECT_EQ("android", package);
+ EXPECT_EQ("string", type);
+ EXPECT_EQ("foo", entry);
+
+ ASSERT_TRUE(ExtractResourceName("string/foo", &package, &type, &entry));
+ EXPECT_EQ("", package);
+ EXPECT_EQ("string", type);
+ EXPECT_EQ("foo", entry);
+
+ ASSERT_TRUE(ExtractResourceName("foo", &package, &type, &entry));
+ EXPECT_EQ("", package);
+ EXPECT_EQ("", type);
+ EXPECT_EQ("foo", entry);
+
+ ASSERT_TRUE(ExtractResourceName("android:foo", &package, &type, &entry));
+ EXPECT_EQ("android", package);
+ EXPECT_EQ("", type);
+ EXPECT_EQ("foo", entry);
+
+ EXPECT_FALSE(ExtractResourceName(":string/foo", &package, &type, &entry));
+ EXPECT_FALSE(ExtractResourceName("/foo", &package, &type, &entry));
+}
+
+} // namespace android
diff --git a/libs/androidfw/tests/Theme_test.cpp b/libs/androidfw/tests/Theme_test.cpp
index daed28b0..dfff9c0 100644
--- a/libs/androidfw/tests/Theme_test.cpp
+++ b/libs/androidfw/tests/Theme_test.cpp
@@ -19,6 +19,7 @@
#include "android-base/logging.h"
#include "TestHelpers.h"
+#include "androidfw/ResourceUtils.h"
#include "data/lib_one/R.h"
#include "data/libclient/R.h"
#include "data/styles/R.h"
@@ -215,9 +216,9 @@
EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
// lib_one is assigned package ID 0x03.
- EXPECT_EQ(3u, util::get_package_id(value.data));
- EXPECT_EQ(util::get_type_id(lib_one::R::string::foo), util::get_type_id(value.data));
- EXPECT_EQ(util::get_entry_id(lib_one::R::string::foo), util::get_entry_id(value.data));
+ EXPECT_EQ(3u, get_package_id(value.data));
+ EXPECT_EQ(get_type_id(lib_one::R::string::foo), get_type_id(value.data));
+ EXPECT_EQ(get_entry_id(lib_one::R::string::foo), get_entry_id(value.data));
}
TEST_F(ThemeTest, CopyThemeSameAssetManager) {
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index 8a6e038..5cf52c6 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -605,6 +605,7 @@
} else {
mDescription.hasExternalTexture = true;
}
+ mDescription.hasLinearTexture = mOutGlop->fill.texture.texture->isLinear();
}
mDescription.hasColors = mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::Color;
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index e70982f..5c8f8e9 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -87,6 +87,7 @@
#define PROGRAM_HAS_ROUND_RECT_CLIP 43
#define PROGRAM_HAS_GAMMA_CORRECTION 44
+#define PROGRAM_HAS_LINEAR_TEXTURE 45
///////////////////////////////////////////////////////////////////////////////
// Types
@@ -162,7 +163,10 @@
bool hasDebugHighlight;
bool hasRoundRectClip;
+ // Extra gamma correction used for text
bool hasGammaCorrection;
+ // Set when sampling an image in linear space
+ bool hasLinearTexture;
/**
* Resets this description. All fields are reset back to the default
@@ -205,6 +209,7 @@
hasRoundRectClip = false;
hasGammaCorrection = false;
+ hasLinearTexture = false;
}
/**
@@ -275,6 +280,7 @@
if (hasDebugHighlight) key |= programid(0x1) << PROGRAM_HAS_DEBUG_HIGHLIGHT;
if (hasRoundRectClip) key |= programid(0x1) << PROGRAM_HAS_ROUND_RECT_CLIP;
if (hasGammaCorrection) key |= programid(0x1) << PROGRAM_HAS_GAMMA_CORRECTION;
+ if (hasLinearTexture) key |= programid(0x1) << PROGRAM_HAS_LINEAR_TEXTURE;
return key;
}
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index 42ef762..ca05648 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -161,9 +161,35 @@
"uniform vec4 roundRectInnerRectLTRB;\n"
"uniform float roundRectRadius;\n";
+const char* gFS_OETF[2] = {
+ "\nvec4 OETF(const vec4 linear) {\n"
+ " return linear;\n"
+ "}\n",
+ // We expect linear data to be scRGB so we mirror the gamma function
+ "\nvec4 OETF(const vec4 linear) {"
+ " return vec4(sign(linear.rgb) * OETF_sRGB(abs(linear.rgb)), linear.a);\n"
+ "}\n",
+};
+
+const char* gFS_Transfer_Functions = R"__SHADER__(
+ float OETF_sRGB(const float linear) {
+ // IEC 61966-2-1:1999
+ return linear <= 0.0031308 ? linear * 12.92 : (pow(linear, 1.0 / 2.4) * 1.055) - 0.055;
+ }
+
+ vec3 OETF_sRGB(const vec3 linear) {
+ return vec3(OETF_sRGB(linear.r), OETF_sRGB(linear.g), OETF_sRGB(linear.b));
+ }
+
+ float EOTF_sRGB(float srgb) {
+ // IEC 61966-2-1:1999
+ return srgb <= 0.04045 ? srgb / 12.92 : pow((srgb + 0.055) / 1.055, 2.4);
+ }
+)__SHADER__";
+
// Dithering must be done in the quantization space
// When we are writing to an sRGB framebuffer, we must do the following:
-// EOCF(OECF(color) + dither)
+// EOTF(OETF(color) + dither)
// The dithering pattern is generated with a triangle noise generator in the range [-0.0,1.0]
// TODO: Handle linear fp16 render targets
const char* gFS_Gradient_Functions = R"__SHADER__(
@@ -173,20 +199,6 @@
highp float xy = p.x * p.y;
return fract(xy * 95.4307) + fract(xy * 75.04961) - 1.0;
}
-
- float OECF_sRGB(const float linear) {
- // IEC 61966-2-1:1999
- return linear <= 0.0031308 ? linear * 12.92 : (pow(linear, 1.0 / 2.4) * 1.055) - 0.055;
- }
-
- vec3 OECF_sRGB(const vec3 linear) {
- return vec3(OECF_sRGB(linear.r), OECF_sRGB(linear.g), OECF_sRGB(linear.b));
- }
-
- float EOCF_sRGB(float srgb) {
- // IEC 61966-2-1:1999
- return srgb <= 0.04045 ? srgb / 12.92 : pow((srgb + 0.055) / 1.055, 2.4);
- }
)__SHADER__";
const char* gFS_Gradient_Preamble[2] = {
// Linear framebuffer
@@ -195,8 +207,8 @@
"}\n"
"\nvec4 gammaMix(const vec4 a, const vec4 b, float v) {\n"
" vec4 c = mix(a, b, v);\n"
- " c.a = EOCF_sRGB(c.a);\n" // This is technically incorrect but preserves compatibility
- " return vec4(OECF_sRGB(c.rgb) * c.a, c.a);\n"
+ " c.a = EOTF_sRGB(c.a);\n" // This is technically incorrect but preserves compatibility
+ " return vec4(OETF_sRGB(c.rgb) * c.a, c.a);\n"
"}\n",
// sRGB framebuffer
"\nvec4 dither(const vec4 color) {\n"
@@ -232,52 +244,6 @@
const char* gFS_Main_AddDither =
" fragColor = dither(fragColor);\n";
-// Fast cases
-const char* gFS_Fast_SingleColor =
- "\nvoid main(void) {\n"
- " gl_FragColor = color;\n"
- "}\n\n";
-const char* gFS_Fast_SingleTexture =
- "\nvoid main(void) {\n"
- " gl_FragColor = texture2D(baseSampler, outTexCoords);\n"
- "}\n\n";
-const char* gFS_Fast_SingleModulateTexture =
- "\nvoid main(void) {\n"
- " gl_FragColor = color.a * texture2D(baseSampler, outTexCoords);\n"
- "}\n\n";
-const char* gFS_Fast_SingleA8Texture =
- "\nvoid main(void) {\n"
- " gl_FragColor = texture2D(baseSampler, outTexCoords);\n"
- "}\n\n";
-const char* gFS_Fast_SingleA8Texture_ApplyGamma =
- "\nvoid main(void) {\n"
- " gl_FragColor = vec4(0.0, 0.0, 0.0, pow(texture2D(baseSampler, outTexCoords).a, GAMMA));\n"
- "}\n\n";
-const char* gFS_Fast_SingleModulateA8Texture =
- "\nvoid main(void) {\n"
- " gl_FragColor = color * texture2D(baseSampler, outTexCoords).a;\n"
- "}\n\n";
-const char* gFS_Fast_SingleModulateA8Texture_ApplyGamma =
- "\nvoid main(void) {\n"
- " gl_FragColor = color * gamma(texture2D(baseSampler, outTexCoords).a, color.rgb);\n"
- "}\n\n";
-const char* gFS_Fast_SingleGradient[2] = {
- "\nvoid main(void) {\n"
- " gl_FragColor = dither(texture2D(gradientSampler, linear));\n"
- "}\n\n",
- "\nvoid main(void) {\n"
- " gl_FragColor = dither(gammaMix(startColor, endColor, clamp(linear, 0.0, 1.0)));\n"
- "}\n\n",
-};
-const char* gFS_Fast_SingleModulateGradient[2] = {
- "\nvoid main(void) {\n"
- " gl_FragColor = dither(color.a * texture2D(gradientSampler, linear));\n"
- "}\n\n",
- "\nvoid main(void) {\n"
- " gl_FragColor = dither(color.a * gammaMix(startColor, endColor, clamp(linear, 0.0, 1.0)));\n"
- "}\n\n"
-};
-
// General case
const char* gFS_Main_FetchColor =
" fragColor = color;\n";
@@ -290,7 +256,7 @@
" fragColor *= texture2D(baseSampler, vec2(alpha, 0.5)).a;\n";
const char* gFS_Main_FetchTexture[2] = {
// Don't modulate
- " fragColor = texture2D(baseSampler, outTexCoords);\n",
+ " fragColor = OETF(texture2D(baseSampler, outTexCoords));\n",
// Modulate
" fragColor = color * texture2D(baseSampler, outTexCoords);\n"
};
@@ -321,9 +287,9 @@
" vec4 gradientColor = gammaMix(startColor, endColor, clamp(index - floor(index), 0.0, 1.0));\n"
};
const char* gFS_Main_FetchBitmap =
- " vec4 bitmapColor = texture2D(bitmapSampler, outBitmapTexCoords);\n";
+ " vec4 bitmapColor = OETF(texture2D(bitmapSampler, outBitmapTexCoords));\n";
const char* gFS_Main_FetchBitmapNpot =
- " vec4 bitmapColor = texture2D(bitmapSampler, wrap(outBitmapTexCoords));\n";
+ " vec4 bitmapColor = OETF(texture2D(bitmapSampler, wrap(outBitmapTexCoords)));\n";
const char* gFS_Main_BlendShadersBG =
" fragColor = blendShaders(gradientColor, bitmapColor)";
const char* gFS_Main_BlendShadersGB =
@@ -649,71 +615,6 @@
shader.appendFormat(gFS_Gamma_Preamble, Properties::textGamma, 1.0f / Properties::textGamma);
}
- // Optimization for common cases
- if (!description.hasVertexAlpha
- && !blendFramebuffer
- && !description.hasColors
- && description.colorOp == ProgramDescription::ColorFilterMode::None
- && !description.hasDebugHighlight
- && !description.hasRoundRectClip) {
- bool fast = false;
-
- const bool noShader = !description.hasGradient && !description.hasBitmap;
- const bool singleTexture = (description.hasTexture || description.hasExternalTexture) &&
- !description.hasAlpha8Texture && noShader;
- const bool singleA8Texture = description.hasTexture &&
- description.hasAlpha8Texture && noShader;
- const bool singleGradient = !description.hasTexture && !description.hasExternalTexture &&
- description.hasGradient && !description.hasBitmap &&
- description.gradientType == ProgramDescription::kGradientLinear;
-
- if (singleColor) {
- shader.append(gFS_Fast_SingleColor);
- fast = true;
- } else if (singleTexture) {
- if (!description.modulate) {
- shader.append(gFS_Fast_SingleTexture);
- } else {
- shader.append(gFS_Fast_SingleModulateTexture);
- }
- fast = true;
- } else if (singleA8Texture) {
- if (!description.modulate) {
- if (description.hasGammaCorrection) {
- shader.append(gFS_Fast_SingleA8Texture_ApplyGamma);
- } else {
- shader.append(gFS_Fast_SingleA8Texture);
- }
- } else {
- if (description.hasGammaCorrection) {
- shader.append(gFS_Fast_SingleModulateA8Texture_ApplyGamma);
- } else {
- shader.append(gFS_Fast_SingleModulateA8Texture);
- }
- }
- fast = true;
- } else if (singleGradient) {
- shader.append(gFS_Gradient_Functions);
- shader.append(gFS_Gradient_Preamble[mHasSRGB]);
- if (!description.modulate) {
- shader.append(gFS_Fast_SingleGradient[description.isSimpleGradient]);
- } else {
- shader.append(gFS_Fast_SingleModulateGradient[description.isSimpleGradient]);
- }
- fast = true;
- }
-
- if (fast) {
-#if DEBUG_PROGRAMS
- PROGRAM_LOGD("*** Fast case:\n");
- PROGRAM_LOGD("*** Generated fragment shader:\n\n");
- printLongString(shader);
-#endif
-
- return shader;
- }
- }
-
if (description.hasBitmap) {
if (description.isShaderBitmapExternal) {
shader.append(gFS_Uniforms_BitmapExternalSampler);
@@ -736,6 +637,13 @@
if (description.useShaderBasedWrap) {
generateTextureWrap(shader, description.bitmapWrapS, description.bitmapWrapT);
}
+ if (description.hasGradient || description.hasLinearTexture) {
+ shader.append(gFS_Transfer_Functions);
+ }
+ if (description.hasBitmap || ((description.hasTexture || description.hasExternalTexture) &&
+ !description.hasAlpha8Texture)) {
+ shader.append(gFS_OETF[description.hasLinearTexture && !mHasSRGB]);
+ }
if (description.hasGradient) {
shader.append(gFS_Gradient_Functions);
shader.append(gFS_Gradient_Preamble[mHasSRGB]);
diff --git a/libs/hwui/Texture.cpp b/libs/hwui/Texture.cpp
index f6850a1..50af9c8 100644
--- a/libs/hwui/Texture.cpp
+++ b/libs/hwui/Texture.cpp
@@ -48,6 +48,10 @@
}
}
+bool Texture::isLinear() const {
+ return mInternalFormat == GL_RGBA16F;
+}
+
void Texture::setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture, bool force) {
if (force || wrapS != mWrapS || wrapT != mWrapT) {
diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h
index b8397cc..ce9d4dc 100644
--- a/libs/hwui/Texture.h
+++ b/libs/hwui/Texture.h
@@ -128,6 +128,11 @@
}
/**
+ * Returns true if this texture uses a linear encoding format.
+ */
+ bool isLinear() const;
+
+ /**
* Generation of the backing bitmap,
*/
uint32_t generation = 0;
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index fb79272..11614fa 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -667,11 +667,17 @@
}
int RenderProxy::copyGraphicBufferInto(GraphicBuffer* buffer, SkBitmap* bitmap) {
- SETUP_TASK(copyGraphicBufferInto);
- args->thread = &RenderThread::getInstance();
- args->bitmap = bitmap;
- args->buffer = buffer;
- return static_cast<int>(reinterpret_cast<intptr_t>(staticPostAndWait(task)));
+ RenderThread& thread = RenderThread::getInstance();
+ if (Properties::isSkiaEnabled() && gettid() == thread.getTid()) {
+ //TODO: fix everything that hits this. We should never be triggering a readback ourselves.
+ return (int) thread.readback().copyGraphicBufferInto(buffer, bitmap);
+ } else {
+ SETUP_TASK(copyGraphicBufferInto);
+ args->thread = &thread;
+ args->bitmap = bitmap;
+ args->buffer = buffer;
+ return static_cast<int>(reinterpret_cast<intptr_t>(staticPostAndWait(task)));
+ }
}
void RenderProxy::post(RenderTask* task) {
@@ -690,6 +696,7 @@
void* RenderProxy::staticPostAndWait(MethodInvokeRenderTask* task) {
RenderThread& thread = RenderThread::getInstance();
+ LOG_ALWAYS_FATAL_IF(gettid() == thread.getTid());
void* retval;
task->setReturnPtr(&retval);
thread.queueAndWait(task);
diff --git a/libs/hwui/tests/common/TestContext.cpp b/libs/hwui/tests/common/TestContext.cpp
index 5e937f3..c1ca1e7 100644
--- a/libs/hwui/tests/common/TestContext.cpp
+++ b/libs/hwui/tests/common/TestContext.cpp
@@ -16,6 +16,8 @@
#include "tests/common/TestContext.h"
+#include <cutils/trace.h>
+
namespace android {
namespace uirenderer {
namespace test {
@@ -98,6 +100,11 @@
}
void TestContext::waitForVsync() {
+ // Hacky fix for not getting sysprop change callbacks
+ // We just poll the sysprop in vsync since it's when the UI thread is
+ // "idle" and shouldn't burn too much time
+ atrace_update_tags();
+
if (mConsumer.get()) {
BufferItem buffer;
if (mConsumer->acquireBuffer(&buffer, 0, false) == OK) {
diff --git a/libs/hwui/tests/common/scenes/ShadowShaderAnimation.cpp b/libs/hwui/tests/common/scenes/ShadowShaderAnimation.cpp
new file mode 100644
index 0000000..fac3968
--- /dev/null
+++ b/libs/hwui/tests/common/scenes/ShadowShaderAnimation.cpp
@@ -0,0 +1,68 @@
+/*
+ * 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 "TestSceneBase.h"
+
+class ShadowShaderAnimation;
+
+static TestScene::Registrar _ShadowShader(TestScene::Info{
+ "shadowshader",
+ "A set of overlapping shadowed areas with simple tessellation useful for"
+ " benchmarking shadow shader performance.",
+ TestScene::simpleCreateScene<ShadowShaderAnimation>
+});
+
+class ShadowShaderAnimation : public TestScene {
+public:
+ std::vector< sp<RenderNode> > cards;
+ void createContent(int width, int height, Canvas& canvas) override {
+ canvas.drawColor(0xFFFFFFFF, SkBlendMode::kSrcOver);
+ canvas.insertReorderBarrier(true);
+
+ int outset = 50;
+ for (int i = 0; i < 10; i++) {
+ sp<RenderNode> card = createCard(outset, outset,
+ width - (outset * 2), height - (outset * 2));
+ canvas.drawRenderNode(card.get());
+ cards.push_back(card);
+ }
+
+ canvas.insertReorderBarrier(false);
+ }
+ void doFrame(int frameNr) override {
+ int curFrame = frameNr % 10;
+ for (size_t ci = 0; ci < cards.size(); ci++) {
+ cards[ci]->mutateStagingProperties().setTranslationX(curFrame);
+ cards[ci]->mutateStagingProperties().setTranslationY(curFrame);
+ cards[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+ }
+ }
+private:
+ sp<RenderNode> createCard(int x, int y, int width, int height) {
+ return TestUtils::createNode(x, y, x + width, y + height,
+ [width, height](RenderProperties& props, Canvas& canvas) {
+ props.setElevation(1000);
+
+ // Set 0 radius, no clipping, so shadow is easy to compute. Slightly transparent outline
+ // to signal contents aren't opaque (not necessary though, as elevation is so high, no
+ // inner content to cut out)
+ props.mutableOutline().setRoundRect(0, 0, width, height, 0, 0.99f);
+ props.mutableOutline().setShouldClip(false);
+
+ // don't draw anything to card's canvas - we just want the shadow
+ });
+ }
+};
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index 4d332a8..2ca36ea 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -26,6 +26,7 @@
import android.media.MediaFormat;
import android.media.MediaHTTPService;
import android.net.Uri;
+import android.os.Bundle;
import android.os.IBinder;
import com.android.internal.util.Preconditions;
@@ -598,6 +599,16 @@
*/
public native boolean hasCacheReachedEndOfStream();
+ /**
+ * Returns Analytics/Metrics data about the current media container.
+ *
+ * @return the set of keys and values available for the media being
+ * handled by this instance of MediaExtractor
+ *
+ */
+ public native Bundle getMetrics();
+
+
private static native final void native_init();
private native final void native_setup();
private native final void native_finalize();
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index b0df0e4..ddbd542e 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -362,6 +362,285 @@
String COLUMN_PACKAGE_NAME = "package_name";
}
+ /**
+ * Common base for the tables of TV programs.
+ */
+ public interface BaseProgramColumns extends BaseTvColumns {
+ /**
+ * The ID of the TV channel that provides this TV program.
+ *
+ * <p>This is a part of the channel URI and matches to {@link BaseColumns#_ID}.
+ *
+ * <p>This is a required field.
+ *
+ * <p>Type: INTEGER (long)
+ */
+ public static final String COLUMN_CHANNEL_ID = "channel_id";
+
+ /**
+ * The title of this TV program.
+ *
+ * <p>If this program is an episodic TV show, it is recommended that the title is the series
+ * title and its related fields ({@link #COLUMN_SEASON_TITLE} and/or
+ * {@link #COLUMN_SEASON_DISPLAY_NUMBER}, {@link #COLUMN_SEASON_DISPLAY_NUMBER},
+ * {@link #COLUMN_EPISODE_DISPLAY_NUMBER}, and {@link #COLUMN_EPISODE_TITLE}) are filled in.
+ *
+ * <p>Type: TEXT
+ */
+ public static final String COLUMN_TITLE = "title";
+
+ /**
+ * The season display number of this TV program for episodic TV shows.
+ *
+ * <p>This is used to indicate the season number. (e.g. 1, 2 or 3) Note that the value
+ * does not necessarily be numeric. (e.g. 12B)
+ *
+ * <p>Can be empty.
+ *
+ * <p>Type: TEXT
+ */
+ public static final String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
+
+ /**
+ * The title of the season for this TV program for episodic TV shows.
+ *
+ * <p>This is an optional field supplied only when the season has a special title
+ * (e.g. The Final Season). If provided, the applications should display it instead of
+ * {@link #COLUMN_SEASON_DISPLAY_NUMBER}, and should display it without alterations.
+ * (e.g. for "The Final Season", displayed string should be "The Final Season", not
+ * "Season The Final Season"). When displaying multiple programs, the order should be based
+ * on {@link #COLUMN_SEASON_DISPLAY_NUMBER}, even when {@link #COLUMN_SEASON_TITLE} exists.
+ *
+ * <p>Can be empty.
+ *
+ * <p>Type: TEXT
+ */
+ public static final String COLUMN_SEASON_TITLE = "season_title";
+
+ /**
+ * The episode display number of this TV program for episodic TV shows.
+ *
+ * <p>This is used to indicate the episode number. (e.g. 1, 2 or 3) Note that the value
+ * does not necessarily be numeric. (e.g. 12B)
+ *
+ * <p>Can be empty.
+ *
+ * <p>Type: TEXT
+ */
+ public static final String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
+
+ /**
+ * The episode title of this TV program for episodic TV shows.
+ *
+ * <p>Can be empty.
+ *
+ * <p>Type: TEXT
+ */
+ public static final String COLUMN_EPISODE_TITLE = "episode_title";
+
+ /**
+ * The comma-separated canonical genre string of this TV program.
+ *
+ * <p>Canonical genres are defined in {@link Genres}. Use {@link Genres#encode} to create a
+ * text that can be stored in this column. Use {@link Genres#decode} to get the canonical
+ * genre strings from the text stored in the column.
+ *
+ * <p>Type: TEXT
+ * @see Genres
+ * @see Genres#encode
+ * @see Genres#decode
+ */
+ public static final String COLUMN_CANONICAL_GENRE = "canonical_genre";
+
+ /**
+ * The short description of this TV program that is displayed to the user by default.
+ *
+ * <p>It is recommended to limit the length of the descriptions to 256 characters.
+ *
+ * <p>Type: TEXT
+ */
+ public static final String COLUMN_SHORT_DESCRIPTION = "short_description";
+
+ /**
+ * The detailed, lengthy description of this TV program that is displayed only when the user
+ * wants to see more information.
+ *
+ * <p>TV input services should leave this field empty if they have no additional details
+ * beyond {@link #COLUMN_SHORT_DESCRIPTION}.
+ *
+ * <p>Type: TEXT
+ */
+ public static final String COLUMN_LONG_DESCRIPTION = "long_description";
+
+ /**
+ * The width of the video for this TV program, in the unit of pixels.
+ *
+ * <p>Together with {@link #COLUMN_VIDEO_HEIGHT} this is used to determine the video
+ * resolution of the current TV program. Can be empty if it is not known initially or the
+ * program does not convey any video such as the programs from type
+ * {@link Channels#SERVICE_TYPE_AUDIO} channels.
+ *
+ * <p>Type: INTEGER
+ */
+ public static final String COLUMN_VIDEO_WIDTH = "video_width";
+
+ /**
+ * The height of the video for this TV program, in the unit of pixels.
+ *
+ * <p>Together with {@link #COLUMN_VIDEO_WIDTH} this is used to determine the video
+ * resolution of the current TV program. Can be empty if it is not known initially or the
+ * program does not convey any video such as the programs from type
+ * {@link Channels#SERVICE_TYPE_AUDIO} channels.
+ *
+ * <p>Type: INTEGER
+ */
+ public static final String COLUMN_VIDEO_HEIGHT = "video_height";
+
+ /**
+ * The comma-separated audio languages of this TV program.
+ *
+ * <p>This is used to describe available audio languages included in the program. Use either
+ * ISO 639-1 or 639-2/T codes.
+ *
+ * <p>Type: TEXT
+ */
+ public static final String COLUMN_AUDIO_LANGUAGE = "audio_language";
+
+ /**
+ * The comma-separated content ratings of this TV program.
+ *
+ * <p>This is used to describe the content rating(s) of this program. Each comma-separated
+ * content rating sub-string should be generated by calling
+ * {@link TvContentRating#flattenToString}. Note that in most cases the program content is
+ * rated by a single rating system, thus resulting in a corresponding single sub-string that
+ * does not require comma separation and multiple sub-strings appear only when the program
+ * content is rated by two or more content rating systems. If any of those ratings is
+ * specified as "blocked rating" in the user's parental control settings, the TV input
+ * service should block the current content and wait for the signal that it is okay to
+ * unblock.
+ *
+ * <p>Type: TEXT
+ */
+ public static final String COLUMN_CONTENT_RATING = "content_rating";
+
+ /**
+ * The URI for the poster art of this TV program.
+ *
+ * <p>The data in the column must be a URL, or a URI in one of the following formats:
+ *
+ * <ul>
+ * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
+ * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
+ * </li>
+ * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
+ * </ul>
+ *
+ * <p>Can be empty.
+ *
+ * <p>Type: TEXT
+ */
+ public static final String COLUMN_POSTER_ART_URI = "poster_art_uri";
+
+ /**
+ * The URI for the thumbnail of this TV program.
+ *
+ * <p>The system can generate a thumbnail from the poster art if this column is not
+ * specified. Thus it is not necessary for TV input services to include a thumbnail if it is
+ * just a scaled image of the poster art.
+ *
+ * <p>The data in the column must be a URL, or a URI in one of the following formats:
+ *
+ * <ul>
+ * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
+ * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
+ * </li>
+ * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
+ * </ul>
+ *
+ * <p>Can be empty.
+ *
+ * <p>Type: TEXT
+ */
+ public static final String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
+
+ /**
+ * The flag indicating whether this TV program is searchable or not.
+ *
+ * <p>The columns of searchable programs can be read by other applications that have proper
+ * permission. Care must be taken not to open sensitive data.
+ *
+ * <p>A value of 1 indicates that the program is searchable and its columns can be read by
+ * other applications, a value of 0 indicates that the program is hidden and its columns can
+ * be read only by the package that owns the program and the system. If not specified, this
+ * value is set to 1 (searchable) by default.
+ *
+ * <p>Type: INTEGER (boolean)
+ */
+ public static final String COLUMN_SEARCHABLE = "searchable";
+
+ /**
+ * Internal data used by individual TV input services.
+ *
+ * <p>This is internal to the provider that inserted it, and should not be decoded by other
+ * apps.
+ *
+ * <p>Type: BLOB
+ */
+ public static final String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
+
+ /**
+ * Internal integer flag used by individual TV input services.
+ *
+ * <p>This is internal to the provider that inserted it, and should not be decoded by other
+ * apps.
+ *
+ * <p>Type: INTEGER
+ */
+ public static final String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
+
+ /**
+ * Internal integer flag used by individual TV input services.
+ *
+ * <p>This is internal to the provider that inserted it, and should not be decoded by other
+ * apps.
+ *
+ * <p>Type: INTEGER
+ */
+ public static final String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
+
+ /**
+ * Internal integer flag used by individual TV input services.
+ *
+ * <p>This is internal to the provider that inserted it, and should not be decoded by other
+ * apps.
+ *
+ * <p>Type: INTEGER
+ */
+ public static final String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
+
+ /**
+ * Internal integer flag used by individual TV input services.
+ *
+ * <p>This is internal to the provider that inserted it, and should not be decoded by other
+ * apps.
+ *
+ * <p>Type: INTEGER
+ */
+ public static final String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
+
+ /**
+ * The version number of this row entry used by TV input services.
+ *
+ * <p>This is best used by sync adapters to identify the rows to update. The number can be
+ * defined by individual TV input services. One may assign the same value as
+ * {@code version_number} in ETSI EN 300 468 or ATSC A/65, if the data are coming from a TV
+ * broadcast.
+ *
+ * <p>Type: INTEGER
+ */
+ public static final String COLUMN_VERSION_NUMBER = "version_number";
+ }
+
/** Column definitions for the TV channels table. */
public static final class Channels implements BaseTvColumns {
@@ -1158,7 +1437,7 @@
* <p>By default, the query results will be sorted by
* {@link Programs#COLUMN_START_TIME_UTC_MILLIS} in ascending order.
*/
- public static final class Programs implements BaseTvColumns {
+ public static final class Programs implements BaseProgramColumns {
/** The content:// style URI for this table. */
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
@@ -1471,17 +1750,6 @@
"REVIEW_RATING_STYLE_PERCENTAGE";
/**
- * The ID of the TV channel that provides this TV program.
- *
- * <p>This is a part of the channel URI and matches to {@link BaseColumns#_ID}.
- *
- * <p>This is a required field.
- *
- * <p>Type: INTEGER (long)
- */
- public static final String COLUMN_CHANNEL_ID = "channel_id";
-
- /**
* The type of this program content.
*
* <p>The value should match one of the followings:
@@ -1520,18 +1788,6 @@
public static final String COLUMN_WATCH_NEXT_TYPE = "watch_next_type";
/**
- * The title of this TV program.
- *
- * <p>If this program is an episodic TV show, it is recommended that the title is the series
- * title and its related fields ({@link #COLUMN_SEASON_TITLE} and/or
- * {@link #COLUMN_SEASON_DISPLAY_NUMBER}, {@link #COLUMN_SEASON_DISPLAY_NUMBER},
- * {@link #COLUMN_EPISODE_DISPLAY_NUMBER}, and {@link #COLUMN_EPISODE_TITLE}) are filled in.
- *
- * <p>Type: TEXT
- */
- public static final String COLUMN_TITLE = "title";
-
- /**
* The season number of this TV program for episodic TV shows.
*
* <p>Can be empty.
@@ -1544,34 +1800,6 @@
public static final String COLUMN_SEASON_NUMBER = "season_number";
/**
- * The season display number of this TV program for episodic TV shows.
- *
- * <p>This is used to indicate the season number. (e.g. 1, 2 or 3) Note that the value
- * does not necessarily be numeric. (e.g. 12B)
- *
- * <p>Can be empty.
- *
- * <p>Type: TEXT
- */
- public static final String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
-
- /**
- * The title of the season for this TV program for episodic TV shows.
- *
- * <p>This is an optional field supplied only when the season has a special title
- * (e.g. The Final Season). If provided, the applications should display it instead of
- * {@link #COLUMN_SEASON_DISPLAY_NUMBER}, and should display it without alterations.
- * (e.g. for "The Final Season", displayed string should be "The Final Season", not
- * "Season The Final Season"). When displaying multiple programs, the order should be based
- * on {@link #COLUMN_SEASON_DISPLAY_NUMBER}, even when {@link #COLUMN_SEASON_TITLE} exists.
- *
- * <p>Can be empty.
- *
- * <p>Type: TEXT
- */
- public static final String COLUMN_SEASON_TITLE = "season_title";
-
- /**
* The episode number of this TV program for episodic TV shows.
*
* <p>Can be empty.
@@ -1583,28 +1811,7 @@
@Deprecated
public static final String COLUMN_EPISODE_NUMBER = "episode_number";
- /**
- * The episode display number of this TV program for episodic TV shows.
- *
- * <p>This is used to indicate the episode number. (e.g. 1, 2 or 3) Note that the value
- * does not necessarily be numeric. (e.g. 12B)
- *
- * <p>Can be empty.
- *
- * <p>Type: TEXT
- */
- public static final String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
-
- /**
- * The episode title of this TV program for episodic TV shows.
- *
- * <p>Can be empty.
- *
- * <p>Type: TEXT
- */
- public static final String COLUMN_EPISODE_TITLE = "episode_title";
-
- /**
+ /**
* The start time of this TV program, in milliseconds since the epoch.
*
* <p>The value should be equal to or larger than {@link #COLUMN_END_TIME_UTC_MILLIS} of the
@@ -1647,109 +1854,6 @@
public static final String COLUMN_BROADCAST_GENRE = "broadcast_genre";
/**
- * The comma-separated canonical genre string of this TV program.
- *
- * <p>Canonical genres are defined in {@link Genres}. Use {@link Genres#encode} to create a
- * text that can be stored in this column. Use {@link Genres#decode} to get the canonical
- * genre strings from the text stored in the column.
- *
- * <p>Type: TEXT
- * @see Genres
- * @see Genres#encode
- * @see Genres#decode
- */
- public static final String COLUMN_CANONICAL_GENRE = "canonical_genre";
-
- /**
- * The short description of this TV program that is displayed to the user by default.
- *
- * <p>It is recommended to limit the length of the descriptions to 256 characters.
- *
- * <p>Type: TEXT
- */
- public static final String COLUMN_SHORT_DESCRIPTION = "short_description";
-
- /**
- * The detailed, lengthy description of this TV program that is displayed only when the user
- * wants to see more information.
- *
- * <p>TV input services should leave this field empty if they have no additional details
- * beyond {@link #COLUMN_SHORT_DESCRIPTION}.
- *
- * <p>Type: TEXT
- */
- public static final String COLUMN_LONG_DESCRIPTION = "long_description";
-
- /**
- * The width of the video for this TV program, in the unit of pixels.
- *
- * <p>Together with {@link #COLUMN_VIDEO_HEIGHT} this is used to determine the video
- * resolution of the current TV program. Can be empty if it is not known initially or the
- * program does not convey any video such as the programs from type
- * {@link Channels#SERVICE_TYPE_AUDIO} channels.
- *
- * <p>Type: INTEGER
- */
- public static final String COLUMN_VIDEO_WIDTH = "video_width";
-
- /**
- * The height of the video for this TV program, in the unit of pixels.
- *
- * <p>Together with {@link #COLUMN_VIDEO_WIDTH} this is used to determine the video
- * resolution of the current TV program. Can be empty if it is not known initially or the
- * program does not convey any video such as the programs from type
- * {@link Channels#SERVICE_TYPE_AUDIO} channels.
- *
- * <p>Type: INTEGER
- */
- public static final String COLUMN_VIDEO_HEIGHT = "video_height";
-
- /**
- * The comma-separated audio languages of this TV program.
- *
- * <p>This is used to describe available audio languages included in the program. Use either
- * ISO 639-1 or 639-2/T codes.
- *
- * <p>Type: TEXT
- */
- public static final String COLUMN_AUDIO_LANGUAGE = "audio_language";
-
- /**
- * The comma-separated content ratings of this TV program.
- *
- * <p>This is used to describe the content rating(s) of this program. Each comma-separated
- * content rating sub-string should be generated by calling
- * {@link TvContentRating#flattenToString}. Note that in most cases the program content is
- * rated by a single rating system, thus resulting in a corresponding single sub-string that
- * does not require comma separation and multiple sub-strings appear only when the program
- * content is rated by two or more content rating systems. If any of those ratings is
- * specified as "blocked rating" in the user's parental control settings, the TV input
- * service should block the current content and wait for the signal that it is okay to
- * unblock.
- *
- * <p>Type: TEXT
- */
- public static final String COLUMN_CONTENT_RATING = "content_rating";
-
- /**
- * The URI for the poster art of this TV program.
- *
- * <p>The data in the column must be a URL, or a URI in one of the following formats:
- *
- * <ul>
- * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
- * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
- * </li>
- * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
- * </ul>
- *
- * <p>Can be empty.
- *
- * <p>Type: TEXT
- */
- public static final String COLUMN_POSTER_ART_URI = "poster_art_uri";
-
- /**
* The aspect ratio of the poster art for this TV program.
*
* <p>The value should match one of the followings:
@@ -1763,28 +1867,6 @@
public static final String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
/**
- * The URI for the thumbnail of this TV program.
- *
- * <p>The system can generate a thumbnail from the poster art if this column is not
- * specified. Thus it is not necessary for TV input services to include a thumbnail if it is
- * just a scaled image of the poster art.
- *
- * <p>The data in the column must be a URL, or a URI in one of the following formats:
- *
- * <ul>
- * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
- * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
- * </li>
- * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
- * </ul>
- *
- * <p>Can be empty.
- *
- * <p>Type: TEXT
- */
- public static final String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
-
- /**
* The aspect ratio of the thumbnail for this TV program.
*
* <p>The value should match one of the followings:
@@ -1883,21 +1965,6 @@
public static final String COLUMN_LIVE = "live";
/**
- * The flag indicating whether this TV program is searchable or not.
- *
- * <p>The columns of searchable programs can be read by other applications that have proper
- * permission. Care must be taken not to open sensitive data.
- *
- * <p>A value of 1 indicates that the program is searchable and its columns can be read by
- * other applications, a value of 0 indicates that the program is hidden and its columns can
- * be read only by the package that owns the program and the system. If not specified, this
- * value is set to 1 (searchable) by default.
- *
- * <p>Type: INTEGER (boolean)
- */
- public static final String COLUMN_SEARCHABLE = "searchable";
-
- /**
* The flag indicating whether recording of this program is prohibited.
*
* <p>A value of 1 indicates that recording of this program is prohibited and application
@@ -1910,68 +1977,6 @@
public static final String COLUMN_RECORDING_PROHIBITED = "recording_prohibited";
/**
- * Internal data used by individual TV input services.
- *
- * <p>This is internal to the provider that inserted it, and should not be decoded by other
- * apps.
- *
- * <p>Type: BLOB
- */
- public static final String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
-
- /**
- * Internal integer flag used by individual TV input services.
- *
- * <p>This is internal to the provider that inserted it, and should not be decoded by other
- * apps.
- *
- * <p>Type: INTEGER
- */
- public static final String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
-
- /**
- * Internal integer flag used by individual TV input services.
- *
- * <p>This is internal to the provider that inserted it, and should not be decoded by other
- * apps.
- *
- * <p>Type: INTEGER
- */
- public static final String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
-
- /**
- * Internal integer flag used by individual TV input services.
- *
- * <p>This is internal to the provider that inserted it, and should not be decoded by other
- * apps.
- *
- * <p>Type: INTEGER
- */
- public static final String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
-
- /**
- * Internal integer flag used by individual TV input services.
- *
- * <p>This is internal to the provider that inserted it, and should not be decoded by other
- * apps.
- *
- * <p>Type: INTEGER
- */
- public static final String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
-
- /**
- * The version number of this row entry used by TV input services.
- *
- * <p>This is best used by sync adapters to identify the rows to update. The number can be
- * defined by individual TV input services. One may assign the same value as
- * {@code version_number} in ETSI EN 300 468 or ATSC A/65, if the data are coming from a TV
- * broadcast.
- *
- * <p>Type: INTEGER
- */
- public static final String COLUMN_VERSION_NUMBER = "version_number";
-
- /**
* The internal ID used by individual TV input services.
*
* <p>This is internal to the provider that inserted it, and should not be decoded by other
@@ -2341,7 +2346,7 @@
* <p>By default, the query results will be sorted by {@link #COLUMN_START_TIME_UTC_MILLIS} in
* ascending order.
*/
- public static final class RecordedPrograms implements BaseTvColumns {
+ public static final class RecordedPrograms implements BaseProgramColumns {
/** The content:// style URI for this table. */
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
@@ -2365,83 +2370,6 @@
public static final String COLUMN_INPUT_ID = "input_id";
/**
- * The ID of the TV channel that provided this recorded TV program.
- *
- * <p>This is a part of the channel URI and matches to {@link BaseColumns#_ID}.
- *
- * <p>This is a required field.
- *
- * <p>Type: INTEGER (long)
- * @see Programs#COLUMN_CHANNEL_ID
- */
- public static final String COLUMN_CHANNEL_ID = Programs.COLUMN_CHANNEL_ID;
-
- /**
- * The title of this recorded TV program.
- *
- * <p>If this recorded program is an episodic TV show, it is recommended that the title is
- * the series title and its related fields ({@link #COLUMN_SEASON_TITLE} and/or
- * {@link #COLUMN_SEASON_DISPLAY_NUMBER}, {@link #COLUMN_EPISODE_DISPLAY_NUMBER},
- * and {@link #COLUMN_EPISODE_TITLE}) are filled in.
- *
- * <p>Type: TEXT
- * @see Programs#COLUMN_TITLE
- */
- public static final String COLUMN_TITLE = Programs.COLUMN_TITLE;
-
- /**
- * The season display number of this recorded TV program for episodic TV shows.
- *
- * <p>This is used to indicate the season number. (e.g. 1, 2 or 3) Note that the value
- * does not necessarily be numeric. (e.g. 12B)
- *
- * <p>Can be empty.
- *
- * <p>Type: TEXT
- */
- public static final String COLUMN_SEASON_DISPLAY_NUMBER =
- Programs.COLUMN_SEASON_DISPLAY_NUMBER;
-
- /**
- * The title of the season for this recorded TV program for episodic TV shows.
- *
- * <p>This is an optional field supplied only when the season has a special title
- * (e.g. The Final Season). If provided, the applications should display it instead of
- * {@link #COLUMN_SEASON_DISPLAY_NUMBER} without alterations.
- * (e.g. for "The Final Season", displayed string should be "The Final Season", not
- * "Season The Final Season"). When displaying multiple programs, the order should be based
- * on {@link #COLUMN_SEASON_DISPLAY_NUMBER}, even when {@link #COLUMN_SEASON_TITLE} exists.
- *
- * <p>Can be empty.
- *
- * <p>Type: TEXT
- */
- public static final String COLUMN_SEASON_TITLE = Programs.COLUMN_SEASON_TITLE;
-
- /**
- * The episode display number of this recorded TV program for episodic TV shows.
- *
- * <p>This is used to indicate the episode number. (e.g. 1, 2 or 3) Note that the value
- * does not necessarily be numeric. (e.g. 12B)
- *
- * <p>Can be empty.
- *
- * <p>Type: TEXT
- */
- public static final String COLUMN_EPISODE_DISPLAY_NUMBER =
- Programs.COLUMN_EPISODE_DISPLAY_NUMBER;
-
- /**
- * The episode title of this recorded TV program for episodic TV shows.
- *
- * <p>Can be empty.
- *
- * <p>Type: TEXT
- * @see Programs#COLUMN_EPISODE_TITLE
- */
- public static final String COLUMN_EPISODE_TITLE = Programs.COLUMN_EPISODE_TITLE;
-
- /**
* The start time of the original TV program, in milliseconds since the epoch.
*
* <p>Type: INTEGER (long)
@@ -2474,154 +2402,6 @@
public static final String COLUMN_BROADCAST_GENRE = Programs.COLUMN_BROADCAST_GENRE;
/**
- * The comma-separated canonical genre string of this recorded TV program.
- *
- * <p>Canonical genres are defined in {@link Programs.Genres}. Use
- * {@link Programs.Genres#encode Genres.encode()} to create a text that can be stored in
- * this column. Use {@link Programs.Genres#decode Genres.decode()} to get the canonical
- * genre strings from the text stored in the column.
- *
- * <p>Type: TEXT
- * @see Programs#COLUMN_CANONICAL_GENRE
- * @see Programs.Genres
- */
- public static final String COLUMN_CANONICAL_GENRE = Programs.COLUMN_CANONICAL_GENRE;
-
- /**
- * The short description of this recorded TV program that is displayed to the user by
- * default.
- *
- * <p>It is recommended to limit the length of the descriptions to 256 characters.
- *
- * <p>Type: TEXT
- * @see Programs#COLUMN_SHORT_DESCRIPTION
- */
- public static final String COLUMN_SHORT_DESCRIPTION = Programs.COLUMN_SHORT_DESCRIPTION;
-
- /**
- * The detailed, lengthy description of this recorded TV program that is displayed only when
- * the user wants to see more information.
- *
- * <p>TV input services should leave this field empty if they have no additional details
- * beyond {@link #COLUMN_SHORT_DESCRIPTION}.
- *
- * <p>Type: TEXT
- * @see Programs#COLUMN_LONG_DESCRIPTION
- */
- public static final String COLUMN_LONG_DESCRIPTION = Programs.COLUMN_LONG_DESCRIPTION;
-
- /**
- * The width of the video for this recorded TV program, in the unit of pixels.
- *
- * <p>Together with {@link #COLUMN_VIDEO_HEIGHT} this is used to determine the video
- * resolution of the current recorded TV program. Can be empty if it is not known or the
- * recorded program does not convey any video.
- *
- * <p>Type: INTEGER
- * @see Programs#COLUMN_VIDEO_WIDTH
- */
- public static final String COLUMN_VIDEO_WIDTH = Programs.COLUMN_VIDEO_WIDTH;
-
- /**
- * The height of the video for this recorded TV program, in the unit of pixels.
- *
- * <p>Together with {@link #COLUMN_VIDEO_WIDTH} this is used to determine the video
- * resolution of the current recorded TV program. Can be empty if it is not known or the
- * recorded program does not convey any video.
- *
- * <p>Type: INTEGER
- * @see Programs#COLUMN_VIDEO_HEIGHT
- */
- public static final String COLUMN_VIDEO_HEIGHT = Programs.COLUMN_VIDEO_HEIGHT;
-
- /**
- * The comma-separated audio languages of this recorded TV program.
- *
- * <p>This is used to describe available audio languages included in the recorded program.
- * Use either ISO 639-1 or 639-2/T codes.
- *
- * <p>Type: TEXT
- * @see Programs#COLUMN_AUDIO_LANGUAGE
- */
- public static final String COLUMN_AUDIO_LANGUAGE = Programs.COLUMN_AUDIO_LANGUAGE;
-
- /**
- * The comma-separated content ratings of this recorded TV program.
- *
- * <p>This is used to describe the content rating(s) of this recorded program. Each
- * comma-separated content rating sub-string should be generated by calling
- * {@link TvContentRating#flattenToString}. Note that in most cases the recorded program
- * content is rated by a single rating system, thus resulting in a corresponding single
- * sub-string that does not require comma separation and multiple sub-strings appear only
- * when the recorded program content is rated by two or more content rating systems. If any
- * of those ratings is specified as "blocked rating" in the user's parental control
- * settings, the TV input service should block the current content and wait for the signal
- * that it is okay to unblock.
- *
- * <p>Type: TEXT
- * @see Programs#COLUMN_CONTENT_RATING
- */
- public static final String COLUMN_CONTENT_RATING = Programs.COLUMN_CONTENT_RATING;
-
- /**
- * The URI for the poster art of this recorded TV program.
- *
- * <p>The data in the column must be a URL, or a URI in one of the following formats:
- *
- * <ul>
- * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
- * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
- * </li>
- * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
- * </ul>
- *
- * <p>Can be empty.
- *
- * <p>Type: TEXT
- * @see Programs#COLUMN_POSTER_ART_URI
- */
- public static final String COLUMN_POSTER_ART_URI = Programs.COLUMN_POSTER_ART_URI;
-
- /**
- * The URI for the thumbnail of this recorded TV program.
- *
- * <p>The system can generate a thumbnail from the poster art if this column is not
- * specified. Thus it is not necessary for TV input services to include a thumbnail if it is
- * just a scaled image of the poster art.
- *
- * <p>The data in the column must be a URL, or a URI in one of the following formats:
- *
- * <ul>
- * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
- * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
- * </li>
- * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
- * </ul>
- *
- * <p>Can be empty.
- *
- * <p>Type: TEXT
- * @see Programs#COLUMN_THUMBNAIL_URI
- */
- public static final String COLUMN_THUMBNAIL_URI = Programs.COLUMN_THUMBNAIL_URI;
-
- /**
- * The flag indicating whether this recorded TV program is searchable or not.
- *
- * <p>The columns of searchable recorded programs can be read by other applications that
- * have proper permission. Care must be taken not to open sensitive data.
- *
- * <p>A value of 1 indicates that the recorded program is searchable and its columns can be
- * read by other applications, a value of 0 indicates that the recorded program is hidden
- * and its columns can be read only by the package that owns the recorded program and the
- * system. If not specified, this value is set to 1 (searchable) by default.
- *
- * <p>Type: INTEGER (boolean)
- * @see Programs#COLUMN_SEARCHABLE
- */
- public static final String COLUMN_SEARCHABLE = Programs.COLUMN_SEARCHABLE;
-
- /**
* The URI of the recording data for this recorded program.
*
* <p>Together with {@link #COLUMN_RECORDING_DATA_BYTES}, applications can use this
@@ -2671,80 +2451,6 @@
public static final String COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS =
"recording_expire_time_utc_millis";
-
- /**
- * Internal data used by individual TV input services.
- *
- * <p>This is internal to the provider that inserted it, and should not be decoded by other
- * apps.
- *
- * <p>Type: BLOB
- * @see Programs#COLUMN_INTERNAL_PROVIDER_DATA
- */
- public static final String COLUMN_INTERNAL_PROVIDER_DATA =
- Programs.COLUMN_INTERNAL_PROVIDER_DATA;
-
- /**
- * Internal integer flag used by individual TV input services.
- *
- * <p>This is internal to the provider that inserted it, and should not be decoded by other
- * apps.
- *
- * <p>Type: INTEGER
- * @see Programs#COLUMN_INTERNAL_PROVIDER_FLAG1
- */
- public static final String COLUMN_INTERNAL_PROVIDER_FLAG1 =
- Programs.COLUMN_INTERNAL_PROVIDER_FLAG1;
-
- /**
- * Internal integer flag used by individual TV input services.
- *
- * <p>This is internal to the provider that inserted it, and should not be decoded by other
- * apps.
- *
- * <p>Type: INTEGER
- * @see Programs#COLUMN_INTERNAL_PROVIDER_FLAG2
- */
- public static final String COLUMN_INTERNAL_PROVIDER_FLAG2 =
- Programs.COLUMN_INTERNAL_PROVIDER_FLAG2;
-
- /**
- * Internal integer flag used by individual TV input services.
- *
- * <p>This is internal to the provider that inserted it, and should not be decoded by other
- * apps.
- *
- * <p>Type: INTEGER
- * @see Programs#COLUMN_INTERNAL_PROVIDER_FLAG3
- */
- public static final String COLUMN_INTERNAL_PROVIDER_FLAG3 =
- Programs.COLUMN_INTERNAL_PROVIDER_FLAG3;
-
- /**
- * Internal integer flag used by individual TV input services.
- *
- * <p>This is internal to the provider that inserted it, and should not be decoded by other
- * apps.
- *
- * <p>Type: INTEGER
- * @see Programs#COLUMN_INTERNAL_PROVIDER_FLAG4
- */
- public static final String COLUMN_INTERNAL_PROVIDER_FLAG4 =
- Programs.COLUMN_INTERNAL_PROVIDER_FLAG4;
-
- /**
- * The version number of this row entry used by TV input services.
- *
- * <p>This is best used by sync adapters to identify the rows to update. The number can be
- * defined by individual TV input services. One may assign the same value as
- * {@code version_number} in ETSI EN 300 468 or ATSC A/65, if the data are coming from a TV
- * broadcast.
- *
- * <p>Type: INTEGER
- * @see Programs#COLUMN_VERSION_NUMBER
- */
- public static final String COLUMN_VERSION_NUMBER = Programs.COLUMN_VERSION_NUMBER;
-
private RecordedPrograms() {}
}
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index 4de1d00..2008f8d 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -19,6 +19,7 @@
#include <utils/Log.h>
#include "android_media_MediaExtractor.h"
+#include "android_media_MediaMetricsJNI.h"
#include "android_media_Utils.h"
#include "android_runtime/AndroidRuntime.h"
@@ -240,6 +241,13 @@
return OK;
}
+status_t JMediaExtractor::getMetrics(Parcel *reply) const {
+
+ status_t status = mImpl->getMetrics(reply);
+ return status;
+}
+
+
status_t JMediaExtractor::getSampleMeta(sp<MetaData> *sampleMeta) {
return mImpl->getSampleMeta(sampleMeta);
}
@@ -767,6 +775,38 @@
android_media_MediaExtractor_release(env, thiz);
}
+static jobject
+android_media_MediaExtractor_getMetrics(JNIEnv * env, jobject thiz)
+{
+ ALOGV("android_media_MediaExtractor_getMetrics");
+
+ sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
+ if (extractor == NULL ) {
+ jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ return NULL;
+ }
+
+ // get what we have for the metrics from the codec
+ Parcel reply;
+ status_t err = extractor->getMetrics(&reply);
+ if (err != OK) {
+ ALOGE("getMetrics failed");
+ return (jobject) NULL;
+ }
+
+ // build and return the Bundle
+ MediaAnalyticsItem *item = new MediaAnalyticsItem;
+ item->readFromParcel(reply);
+ jobject mybundle = MediaMetricsJNI::writeMetricsToBundle(env, item, NULL);
+
+ // housekeeping
+ delete item;
+ item = NULL;
+
+ return mybundle;
+}
+
+
static const JNINativeMethod gMethods[] = {
{ "release", "()V", (void *)android_media_MediaExtractor_release },
@@ -826,6 +866,9 @@
{ "hasCacheReachedEndOfStream", "()Z",
(void *)android_media_MediaExtractor_hasCacheReachedEOS },
+
+ {"getMetrics", "()Landroid/os/Bundle;",
+ (void *)android_media_MediaExtractor_getMetrics},
};
int register_android_media_MediaExtractor(JNIEnv *env) {
diff --git a/media/jni/android_media_MediaExtractor.h b/media/jni/android_media_MediaExtractor.h
index 9f62506..c747ef5 100644
--- a/media/jni/android_media_MediaExtractor.h
+++ b/media/jni/android_media_MediaExtractor.h
@@ -60,6 +60,7 @@
status_t getSampleTime(int64_t *sampleTimeUs);
status_t getSampleFlags(uint32_t *sampleFlags);
status_t getSampleMeta(sp<MetaData> *sampleMeta);
+ status_t getMetrics(Parcel *reply) const;
bool getCachedDuration(int64_t *durationUs, bool *eos) const;
diff --git a/packages/CompanionDeviceManager/AndroidManifest.xml b/packages/CompanionDeviceManager/AndroidManifest.xml
index 3eede54..65cac09 100644
--- a/packages/CompanionDeviceManager/AndroidManifest.xml
+++ b/packages/CompanionDeviceManager/AndroidManifest.xml
@@ -41,7 +41,7 @@
<activity
android:name=".DeviceChooserActivity"
- android:theme="@*android:style/Theme.Dialog.NoFrame"
+ android:theme="@style/ChooserActivity"
android:permission="android.permission.BIND_COMPANION_DEVICE_MANAGER_SERVICE">
<!--TODO include url scheme filter similar to PrintSpooler -->
<intent-filter>
diff --git a/packages/CompanionDeviceManager/res/drawable/dialog_background.xml b/packages/CompanionDeviceManager/res/drawable/dialog_background.xml
new file mode 100644
index 0000000..af2c83f
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/drawable/dialog_background.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<inset xmlns:android="http://schemas.android.com/apk/res/android">
+ <shape android:shape="rectangle">
+ <corners android:radius="2dp" />
+ <solid android:color="?android:attr/colorBackground" />
+ </shape>
+</inset>
diff --git a/packages/CompanionDeviceManager/res/layout/buttons.xml b/packages/CompanionDeviceManager/res/layout/buttons.xml
new file mode 100644
index 0000000..350a791
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/layout/buttons.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/buttons"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentEnd="true"
+ android:gravity="end"
+>
+ <Button
+ android:id="@+id/button_cancel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/cancel"
+ style="@android:style/Widget.Material.Light.Button.Borderless.Colored"
+ />
+ <Button
+ android:id="@+id/button_pair"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/pair"
+ style="@android:style/Widget.Material.Light.Button.Borderless.Colored"
+ />
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/CompanionDeviceManager/res/layout/device_chooser.xml b/packages/CompanionDeviceManager/res/layout/device_chooser.xml
index ee08582..88de33f 100644
--- a/packages/CompanionDeviceManager/res/layout/device_chooser.xml
+++ b/packages/CompanionDeviceManager/res/layout/device_chooser.xml
@@ -16,52 +16,22 @@
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="0.1"
+ android:id="@+id/container"
+ android:layout_height="400dp"
+ style="@style/ContainerLayout"
>
- <TextView
- android:id="@+id/title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:textColor="@android:color/black"
- style="@*android:style/TextAppearance.Widget.Toolbar.Title"
- />
+ <include layout="@layout/title" />
<ListView
android:id="@+id/device_list"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_height="match_parent"
android:layout_below="@+id/title"
android:layout_above="@+id/buttons"
style="@android:style/Widget.Material.Light.ListView"
/>
- <LinearLayout
- android:id="@+id/buttons"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_alignParentBottom="true"
- android:layout_alignParentEnd="true"
- android:gravity="end"
- >
- <Button
- android:id="@+id/button_cancel"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Cancel"
- style="@android:style/Widget.Material.Light.Button.Borderless.Colored"
- />
- <Button
- android:id="@+id/button_pair"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Pair"
- style="@android:style/Widget.Material.Light.Button.Borderless.Colored"
- />
- </LinearLayout>
+ <include layout="@layout/buttons" />
</RelativeLayout>
\ No newline at end of file
diff --git a/packages/CompanionDeviceManager/res/layout/device_confirmation.xml b/packages/CompanionDeviceManager/res/layout/device_confirmation.xml
new file mode 100644
index 0000000..7cde41a
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/layout/device_confirmation.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/container"
+ android:layout_height="wrap_content"
+ style="@style/ContainerLayout"
+ >
+
+ <include layout="@layout/title" />
+
+ <include layout="@layout/buttons" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/CompanionDeviceManager/res/layout/title.xml b/packages/CompanionDeviceManager/res/layout/title.xml
new file mode 100644
index 0000000..dfa71e2
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/layout/title.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+
+<TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textColor="@android:color/black"
+ style="@*android:style/TextAppearance.Widget.Toolbar.Title"
+/>
\ No newline at end of file
diff --git a/packages/CompanionDeviceManager/res/values/strings.xml b/packages/CompanionDeviceManager/res/values/strings.xml
index c4195b50..469c1fb 100644
--- a/packages/CompanionDeviceManager/res/values/strings.xml
+++ b/packages/CompanionDeviceManager/res/values/strings.xml
@@ -22,4 +22,13 @@
<!-- Title of the device selection dialog. -->
<string name="chooser_title">Pair with <strong><xliff:g id="app_name" example="Android Wear">%1$s</xliff:g></strong> via Bluetooth?</string>
+ <!-- Title of the device pairing confirmation dialog. -->
+ <string name="confirmation_title">Pair <strong><xliff:g id="app_name" example="Android Wear">%1$s</xliff:g></strong> with <strong><xliff:g id="device_name" example="ASUS ZenWatch 2">%2$s</xliff:g></strong> via Bluetooth?</string>
+
+ <!-- Label on the pair button in a companion device chooser/confirmation dialog -->
+ <string name="pair">Pair</string>
+
+ <!-- Label on the cancel button in a companion device chooser/confirmation dialog -->
+ <string name="cancel">Cancel</string>
+
</resources>
diff --git a/packages/CompanionDeviceManager/res/values/styles.xml b/packages/CompanionDeviceManager/res/values/styles.xml
new file mode 100644
index 0000000..9dced47b
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values/styles.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+ <style name="ContainerLayout">
+ <item name="android:orientation">vertical</item>
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:elevation">16dp</item>
+ <item name="android:background">@drawable/dialog_background</item>
+ <item name="android:paddingTop">18dip</item>
+ <item name="android:paddingStart">20dip</item>
+ <item name="android:paddingEnd">16dip</item>
+ <item name="android:paddingBottom">16dip</item>
+ <item name="android:layout_gravity">center</item>
+ </style>
+</resources>
\ No newline at end of file
diff --git a/packages/CompanionDeviceManager/res/values/themes.xml b/packages/CompanionDeviceManager/res/values/themes.xml
index 465f8fc..e3fc67c 100644
--- a/packages/CompanionDeviceManager/res/values/themes.xml
+++ b/packages/CompanionDeviceManager/res/values/themes.xml
@@ -16,10 +16,11 @@
<resources>
- <!--TODO-->
- <!--<style name="Theme.ChooserActivity" parent="@*android:style/Theme.Dialog.NoFrame">-->
- <!--<!–<item name="android:windowBackground">@android:color/light_grey</item>–>-->
- <!--<item name="android:backgroundColor">@android:color/light_grey</item>-->
- <!--</style>-->
+ <style name="ChooserActivity"
+ parent="@android:style/Theme.DeviceDefault.Light.Dialog.NoActionBar">
+ <item name="*android:windowFixedHeightMajor">100%</item>
+ <item name="*android:windowFixedHeightMinor">100%</item>
+ <item name="android:windowBackground">@android:color/transparent</item>
+ </style>
</resources>
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
index c95f940..8a970da 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
@@ -16,6 +16,8 @@
package com.android.companiondevicemanager;
+import static android.companion.BluetoothDeviceFilterUtils.getDeviceDisplayName;
+
import android.app.Activity;
import android.bluetooth.BluetoothDevice;
import android.companion.CompanionDeviceManager;
@@ -23,7 +25,6 @@
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.DataSetObserver;
-import android.graphics.Color;
import android.os.Bundle;
import android.text.Html;
import android.util.Log;
@@ -49,29 +50,38 @@
if (DEBUG) Log.i(LOG_TAG, "Started with intent " + getIntent());
- setContentView(R.layout.device_chooser);
- setTitle(Html.fromHtml(getString(R.string.chooser_title, getCallingAppName()), 0));
- getWindow().getDecorView().getRootView().setBackgroundColor(Color.LTGRAY); //TODO theme
-
if (getService().mDevicesFound.isEmpty()) {
Log.e(LOG_TAG, "About to show UI, but no devices to show");
}
- final DeviceDiscoveryService.DevicesAdapter adapter = getService().mDevicesAdapter;
- mDeviceListView = (ListView) findViewById(R.id.device_list);
- mDeviceListView.setAdapter(adapter);
- mDeviceListView.addFooterView(getProgressBar(), null, false);
+ if (getService().mRequest.isSingleDevice()) {
+ setContentView(R.layout.device_confirmation);
+ final BluetoothDevice selectedDevice = getService().mDevicesFound.get(0);
+ setTitle(Html.fromHtml(getString(
+ R.string.confirmation_title,
+ getCallingAppName(),
+ getDeviceDisplayName(selectedDevice)), 0));
+ getService().mSelectedDevice = selectedDevice;
+ } else {
+ setContentView(R.layout.device_chooser);
+ setTitle(Html.fromHtml(getString(R.string.chooser_title, getCallingAppName()), 0));
+ mDeviceListView = (ListView) findViewById(R.id.device_list);
+ final DeviceDiscoveryService.DevicesAdapter adapter = getService().mDevicesAdapter;
+ mDeviceListView.setAdapter(adapter);
+ adapter.registerDataSetObserver(new DataSetObserver() {
+ @Override
+ public void onChanged() {
+ updatePairButtonEnabled();
+ }
+ });
+ mDeviceListView.addFooterView(getProgressBar(), null, false);
+ }
mPairButton = findViewById(R.id.button_pair);
mPairButton.setOnClickListener((view) ->
onPairTapped(getService().mSelectedDevice));
- adapter.registerDataSetObserver(new DataSetObserver() {
- @Override
- public void onChanged() {
- updatePairButtonEnabled();
- }
- });
updatePairButtonEnabled();
+
mCancelButton = findViewById(R.id.button_cancel);
mCancelButton.setOnClickListener((view) -> {
setResult(RESULT_CANCELED);
@@ -108,9 +118,6 @@
static int getPadding(Resources r) {
return r.getDimensionPixelSize(R.dimen.padding);
- //TODO
-// final float dp = r.getDisplayMetrics().density;
-// return (int)(12 * dp);
}
private void updatePairButtonEnabled() {
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
index a3eec0d..ccbee2a 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
@@ -66,6 +66,7 @@
private BluetoothLEDeviceFilter mFilter;
private ScanFilter mScanFilter;
private ScanSettings mDefaultScanSettings = new ScanSettings.Builder().build();
+ AssociationRequest<?> mRequest;
List<BluetoothDevice> mDevicesFound;
BluetoothDevice mSelectedDevice;
DevicesAdapter mDevicesAdapter;
@@ -141,6 +142,7 @@
private void startDiscovery(AssociationRequest<?> request) {
//TODO support other protocols as well
+ mRequest = request;
mFilter = nullsafe((BluetoothLEDeviceFilter) request.getDeviceFilter());
mScanFilter = mFilter.getScanFilter();
diff --git a/packages/SettingsLib/res/color/batterymeter_bolt_color.xml b/packages/SettingsLib/res/color/batterymeter_bolt_color.xml
new file mode 100644
index 0000000..34de548
--- /dev/null
+++ b/packages/SettingsLib/res/color/batterymeter_bolt_color.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:alpha="0.3" android:color="?android:attr/colorForeground" />
+</selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/color/batterymeter_charge_color.xml b/packages/SettingsLib/res/color/batterymeter_charge_color.xml
new file mode 100644
index 0000000..15944c3
--- /dev/null
+++ b/packages/SettingsLib/res/color/batterymeter_charge_color.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="?android:attr/colorForeground" />
+</selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/color/batterymeter_frame_color.xml b/packages/SettingsLib/res/color/batterymeter_frame_color.xml
new file mode 100644
index 0000000..34de548
--- /dev/null
+++ b/packages/SettingsLib/res/color/batterymeter_frame_color.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:alpha="0.3" android:color="?android:attr/colorForeground" />
+</selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/color/dark_mode_icon_color_dual_tone_background.xml b/packages/SettingsLib/res/color/dark_mode_icon_color_dual_tone_background.xml
new file mode 100644
index 0000000..c8a80ac
--- /dev/null
+++ b/packages/SettingsLib/res/color/dark_mode_icon_color_dual_tone_background.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:alpha="0.24" android:color="?android:attr/colorBackground" />
+</selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/color/dark_mode_icon_color_dual_tone_fill.xml b/packages/SettingsLib/res/color/dark_mode_icon_color_dual_tone_fill.xml
new file mode 100644
index 0000000..8dcfdbb
--- /dev/null
+++ b/packages/SettingsLib/res/color/dark_mode_icon_color_dual_tone_fill.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:alpha="0.47" android:color="?android:attr/colorBackground" />
+</selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/color/light_mode_icon_color_dual_tone_background.xml b/packages/SettingsLib/res/color/light_mode_icon_color_dual_tone_background.xml
new file mode 100644
index 0000000..34de548
--- /dev/null
+++ b/packages/SettingsLib/res/color/light_mode_icon_color_dual_tone_background.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:alpha="0.3" android:color="?android:attr/colorForeground" />
+</selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/color/light_mode_icon_color_dual_tone_fill.xml b/packages/SettingsLib/res/color/light_mode_icon_color_dual_tone_fill.xml
new file mode 100644
index 0000000..15944c3
--- /dev/null
+++ b/packages/SettingsLib/res/color/light_mode_icon_color_dual_tone_fill.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="?android:attr/colorForeground" />
+</selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/values-bn/arrays.xml b/packages/SettingsLib/res/values-bn/arrays.xml
index 01ba2cd..b40bfd4 100644
--- a/packages/SettingsLib/res/values-bn/arrays.xml
+++ b/packages/SettingsLib/res/values-bn/arrays.xml
@@ -58,14 +58,22 @@
<item msgid="3878793616631049349">"শুধুমাত্র DRM সামগ্রীর জন্য HDCP চেক করা ব্যবহার করুন"</item>
<item msgid="45075631231212732">"সর্বদা HDCP পরীক্ষণ ব্যবহার করুন"</item>
</string-array>
- <!-- no translation found for bluetooth_a2dp_codec_titles:2 (686685526567131661) -->
- <!-- no translation found for bluetooth_a2dp_codec_titles:3 (8910200421843557332) -->
- <!-- no translation found for bluetooth_a2dp_codec_titles:4 (8434403964359457768) -->
- <!-- no translation found for bluetooth_a2dp_codec_titles:5 (6751080638867012696) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (6839647709301342559) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (2279916056363477395) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (6641171061200063516) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:5 (7950781694447359344) -->
+ <string-array name="bluetooth_a2dp_codec_titles">
+ <item msgid="7065842274271279580">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item>
+ <item msgid="7539690996561263909">"SBC"</item>
+ <item msgid="686685526567131661">"AAC"</item>
+ <item msgid="8910200421843557332">"aptX"</item>
+ <item msgid="8434403964359457768">"aptX HD"</item>
+ <item msgid="6751080638867012696">"LDAC"</item>
+ </string-array>
+ <string-array name="bluetooth_a2dp_codec_summaries">
+ <item msgid="5062108632402595000">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item>
+ <item msgid="6898329690939802290">"SBC"</item>
+ <item msgid="6839647709301342559">"AAC"</item>
+ <item msgid="2279916056363477395">"aptX"</item>
+ <item msgid="6641171061200063516">"aptX HD"</item>
+ <item msgid="7950781694447359344">"LDAC"</item>
+ </string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="3093023430402746802">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item>
<item msgid="8895532488906185219">"৪৪.১ kHz"</item>
@@ -102,10 +110,16 @@
<item msgid="8900559293912978337">"মোনো"</item>
<item msgid="8883739882299884241">"স্টিরিও"</item>
</string-array>
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (7158319962230727476) -->
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (8860982705384396512) -->
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (6398189564246596868) -->
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (4681409244565426925) -->
+ <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+ <item msgid="7158319962230727476">"অডিও গুণমানের জন্য অপ্টিমাইজ করা হয়েছে (৯৯০kbps/৯০৯kbps)"</item>
+ <item msgid="2921767058740704969">"সন্তুলিত গুণমানের অডিও এবং সংযোগ (660kbps/606kbps)"</item>
+ <item msgid="8860982705384396512">"সংযোগের গুণমানের জন্য অপটিমাইজ করা হয়েছে (৩৩০kbps/৩০৩kbps)"</item>
+ </string-array>
+ <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+ <item msgid="6398189564246596868">"অডিও গুণমানের জন্য অপ্টিমাইজ করা হয়েছে"</item>
+ <item msgid="4327143584633311908">"সন্তুলিত গুণমানের অডিও এবং সংযোগ"</item>
+ <item msgid="4681409244565426925">"সংযোগের গুণমানের জন্য অপটিমাইজ করা হয়েছে"</item>
+ </string-array>
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"বন্ধ আছে"</item>
<item msgid="1593289376502312923">"৬৪K"</item>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 8350bb7..08f7227 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -53,7 +53,7 @@
<string name="bluetooth_profile_pbap_summary" msgid="6605229608108852198">"পরিচিতি শেয়ার করার কাজে ব্যবহার করুন"</string>
<string name="bluetooth_profile_pan_nap" msgid="8429049285027482959">"ইন্টারনেট সংযোগ শেয়ার করা হচ্ছে"</string>
<string name="bluetooth_profile_map" msgid="5465271250454324383">"বার্তা অ্যাক্সেস"</string>
- <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM -এর অ্যাক্সেস"</string>
+ <string name="bluetooth_profile_sap" msgid="5764222021851283125">"সিম -এর অ্যাক্সেস"</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>
@@ -65,7 +65,7 @@
<string name="bluetooth_pan_nap_profile_summary_connected" msgid="1561383706411975199">"ডিভাইসের সাথে স্থানীয় ইন্টারনেট সংযোগ ভাগ করছে"</string>
<string name="bluetooth_pan_profile_summary_use_for" msgid="5664884523822068653">"ইন্টারনেট অ্যাক্সেসের জন্য ব্যবহার করুন"</string>
<string name="bluetooth_map_profile_summary_use_for" msgid="5154200119919927434">"মানচিত্রের জন্য ব্যবহার করুন"</string>
- <string name="bluetooth_sap_profile_summary_use_for" msgid="7085362712786907993">"SIM -এর অ্যাক্সেসের জন্য ব্যবহার করুন"</string>
+ <string name="bluetooth_sap_profile_summary_use_for" msgid="7085362712786907993">"সিম -এর অ্যাক্সেসের জন্য ব্যবহার করুন"</string>
<string name="bluetooth_a2dp_profile_summary_use_for" msgid="4630849022250168427">"মিডিয়া অডিওয়ের জন্য ব্যবহার করুন"</string>
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ফোন অডিওয়ের জন্য ব্যবহার করুন"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ফাইল স্থানান্তরের জন্য ব্যবহার করুন"</string>
diff --git a/packages/SettingsLib/res/values-bs/arrays.xml b/packages/SettingsLib/res/values-bs/arrays.xml
index f27f265..1c3d3bf 100644
--- a/packages/SettingsLib/res/values-bs/arrays.xml
+++ b/packages/SettingsLib/res/values-bs/arrays.xml
@@ -111,9 +111,9 @@
<item msgid="8883739882299884241">"Stereo"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
- <item msgid="7158319962230727476">"Optimizirano za kvalitet zvuka (990kbps/909kbps)"</item>
+ <item msgid="7158319962230727476">"Optimizirano za kvalitet zvuka (990 kbps/909 kbps)"</item>
<item msgid="2921767058740704969">"Uravnotežen kvalitet zvuka i veze (660kbps/606kbps)"</item>
- <item msgid="8860982705384396512">"Optimizirano za kvalitet veze (330kbps/303kbps)"</item>
+ <item msgid="8860982705384396512">"Optimizirano za kvalitet veze (330 kbps/303 kbps)"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
<item msgid="6398189564246596868">"Optimizirano za kvalitet zvuka"</item>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 2d36397..8071c83 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -202,7 +202,7 @@
<string name="adb_keys_warning_message" msgid="5659849457135841625">"Vil du ophæve adgangen til USB-fejlfinding for alle computere, du tidligere har godkendt?"</string>
<string name="dev_settings_warning_title" msgid="7244607768088540165">"Vil du tillade udviklingsindstillinger?"</string>
<string name="dev_settings_warning_message" msgid="2298337781139097964">"Disse indstillinger er kun beregnet til brug i forbindelse med udvikling. De kan forårsage, at din enhed og dens applikationer går ned eller ikke fungerer korrekt."</string>
- <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Kontrollér apps via USB"</string>
+ <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verificer apps via USB"</string>
<string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kontrollér apps, der er installeret via ADB/ADT, for skadelig adfærd."</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Deaktiverer funktionen til absolut lydstyrke via Bluetooth i tilfælde af problemer med lydstyrken på eksterne enheder, f.eks. uacceptabel høj lyd eller manglende kontrol."</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Lokal terminal"</string>
diff --git a/packages/SettingsLib/res/values-es/arrays.xml b/packages/SettingsLib/res/values-es/arrays.xml
index 3493c08..d5155c9 100644
--- a/packages/SettingsLib/res/values-es/arrays.xml
+++ b/packages/SettingsLib/res/values-es/arrays.xml
@@ -58,14 +58,22 @@
<item msgid="3878793616631049349">"Utilizar comprobación de HDCP solo para contenido DRM"</item>
<item msgid="45075631231212732">"Utilizar siempre comprobación de HDCP"</item>
</string-array>
- <!-- no translation found for bluetooth_a2dp_codec_titles:2 (686685526567131661) -->
- <!-- no translation found for bluetooth_a2dp_codec_titles:3 (8910200421843557332) -->
- <!-- no translation found for bluetooth_a2dp_codec_titles:4 (8434403964359457768) -->
- <!-- no translation found for bluetooth_a2dp_codec_titles:5 (6751080638867012696) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (6839647709301342559) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (2279916056363477395) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (6641171061200063516) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:5 (7950781694447359344) -->
+ <string-array name="bluetooth_a2dp_codec_titles">
+ <item msgid="7065842274271279580">"Usar preferencia del sistema (predeter.)"</item>
+ <item msgid="7539690996561263909">"SBC"</item>
+ <item msgid="686685526567131661">"AAC"</item>
+ <item msgid="8910200421843557332">"aptX"</item>
+ <item msgid="8434403964359457768">"aptX HD"</item>
+ <item msgid="6751080638867012696">"LDAC"</item>
+ </string-array>
+ <string-array name="bluetooth_a2dp_codec_summaries">
+ <item msgid="5062108632402595000">"Usar preferencia del sistema (predeter.)"</item>
+ <item msgid="6898329690939802290">"SBC"</item>
+ <item msgid="6839647709301342559">"AAC"</item>
+ <item msgid="2279916056363477395">"aptX"</item>
+ <item msgid="6641171061200063516">"aptX HD"</item>
+ <item msgid="7950781694447359344">"LDAC"</item>
+ </string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="3093023430402746802">"Usar preferencia del sistema (predeter.)"</item>
<item msgid="8895532488906185219">"44,1 kHz"</item>
@@ -102,10 +110,16 @@
<item msgid="8900559293912978337">"Mono"</item>
<item msgid="8883739882299884241">"Estéreo"</item>
</string-array>
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (7158319962230727476) -->
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (8860982705384396512) -->
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (6398189564246596868) -->
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (4681409244565426925) -->
+ <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+ <item msgid="7158319962230727476">"Optimizado para la calidad del audio (990 kbps/909 kbps)"</item>
+ <item msgid="2921767058740704969">"Equilibrar la calidad del audio y de la conexión (660/606&nbsp;kbps)"</item>
+ <item msgid="8860982705384396512">"Optimizado para la calidad de la conexión (330 kbps/303 kbps)"</item>
+ </string-array>
+ <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+ <item msgid="6398189564246596868">"Se ha optimizado para la calidad del audio"</item>
+ <item msgid="4327143584633311908">"Equilibrar la calidad del audio y la de la conexión"</item>
+ <item msgid="4681409244565426925">"Se ha optimizado para la calidad de la conexión"</item>
+ </string-array>
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"No"</item>
<item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-eu/arrays.xml b/packages/SettingsLib/res/values-eu/arrays.xml
index 4148a4e..e4bcf482 100644
--- a/packages/SettingsLib/res/values-eu/arrays.xml
+++ b/packages/SettingsLib/res/values-eu/arrays.xml
@@ -111,9 +111,9 @@
<item msgid="8883739882299884241">"Estereoa"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
- <item msgid="7158319962230727476">"Audioaren kalitatea areagotzeko optimizatua (990 kb/s / 909 kb/s)"</item>
- <item msgid="2921767058740704969">"Orekatu audioaren eta konexioaren kalitateak (660 kbps / 606 kbps)"</item>
- <item msgid="8860982705384396512">"Konexioaren kalitatea areagotzeko optimizatua (330 kb/s / 303 kb/s)"</item>
+ <item msgid="7158319962230727476">"Audioaren kalitatea areagotzeko optimizatua (990 Kb/s / 909 Kb/s)"</item>
+ <item msgid="2921767058740704969">"Audioaren eta konexioaren kalitate orekatua (660 Kb/s / 606 Kb/s)"</item>
+ <item msgid="8860982705384396512">"Konexioaren kalitatea areagotzeko optimizatua (330 Kb/s / 303 Kb/s)"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
<item msgid="6398189564246596868">"Audioaren kalitatea areagotzeko optimizatua"</item>
diff --git a/packages/SettingsLib/res/values-gu/arrays.xml b/packages/SettingsLib/res/values-gu/arrays.xml
index e871198..6eb4321 100644
--- a/packages/SettingsLib/res/values-gu/arrays.xml
+++ b/packages/SettingsLib/res/values-gu/arrays.xml
@@ -58,14 +58,22 @@
<item msgid="3878793616631049349">"ફક્ત DRM સામગ્રી માટે HDCP તપાસનો ઉપયોગ કરો"</item>
<item msgid="45075631231212732">"હંમેશા HDCP તપાસનો ઉપયોગ કરો"</item>
</string-array>
- <!-- no translation found for bluetooth_a2dp_codec_titles:2 (686685526567131661) -->
- <!-- no translation found for bluetooth_a2dp_codec_titles:3 (8910200421843557332) -->
- <!-- no translation found for bluetooth_a2dp_codec_titles:4 (8434403964359457768) -->
- <!-- no translation found for bluetooth_a2dp_codec_titles:5 (6751080638867012696) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (6839647709301342559) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (2279916056363477395) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (6641171061200063516) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:5 (7950781694447359344) -->
+ <string-array name="bluetooth_a2dp_codec_titles">
+ <item msgid="7065842274271279580">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item>
+ <item msgid="7539690996561263909">"SBC"</item>
+ <item msgid="686685526567131661">"AAC"</item>
+ <item msgid="8910200421843557332">"aptX"</item>
+ <item msgid="8434403964359457768">"aptX HD"</item>
+ <item msgid="6751080638867012696">"LDAC"</item>
+ </string-array>
+ <string-array name="bluetooth_a2dp_codec_summaries">
+ <item msgid="5062108632402595000">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item>
+ <item msgid="6898329690939802290">"SBC"</item>
+ <item msgid="6839647709301342559">"AAC"</item>
+ <item msgid="2279916056363477395">"aptX"</item>
+ <item msgid="6641171061200063516">"aptX HD"</item>
+ <item msgid="7950781694447359344">"LDAC"</item>
+ </string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="3093023430402746802">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item>
<item msgid="8895532488906185219">"44.1 kHz"</item>
@@ -102,10 +110,16 @@
<item msgid="8900559293912978337">"મૉનો"</item>
<item msgid="8883739882299884241">"સ્ટીરિઓ"</item>
</string-array>
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (7158319962230727476) -->
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (8860982705384396512) -->
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (6398189564246596868) -->
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (4681409244565426925) -->
+ <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+ <item msgid="7158319962230727476">"ઑડિઓની ગુણવત્તા (990 kbps/909 kbps) માટે ઓપ્ટિમાઇઝ કર્યું"</item>
+ <item msgid="2921767058740704969">"સંતુલિત ઑડિઓ અને કનેક્શનની ગુણવત્તા (660kbps/606kbps)"</item>
+ <item msgid="8860982705384396512">"કનેક્શનની ગુણવત્તા (330 kbps/303 kbps) માટે ઓપ્ટિમાઇઝ કર્યું"</item>
+ </string-array>
+ <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+ <item msgid="6398189564246596868">"ઑડિઓની ગુણવત્તા માટે ઓપ્ટિમાઇઝ કર્યું"</item>
+ <item msgid="4327143584633311908">"સંતુલિત ઑડિઓ અને કનેક્શનની ગુણવત્તા"</item>
+ <item msgid="4681409244565426925">"કનેક્શનની ગુણવત્તા માટે ઓપ્ટિમાઇઝ કર્યું"</item>
+ </string-array>
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"બંધ"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-hy/arrays.xml b/packages/SettingsLib/res/values-hy/arrays.xml
index 88f6e78..8925f32 100644
--- a/packages/SettingsLib/res/values-hy/arrays.xml
+++ b/packages/SettingsLib/res/values-hy/arrays.xml
@@ -111,12 +111,12 @@
<item msgid="8883739882299884241">"Ստերեո"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
- <item msgid="7158319962230727476">"Օպտիմալացված ձայնի որակ համար (990 կբ/վ / 909 կբ/վ)"</item>
+ <item msgid="7158319962230727476">"Օպտիմալացված ձայնի որակի համար (990 կբ/վ / 909 կբ/վ)"</item>
<item msgid="2921767058740704969">"Ձայնի և կապի հավասարակշռված որակ (660 կբ/վ / 606 կբ/վ)"</item>
<item msgid="8860982705384396512">"Օպտիմալացված կապի որակի համար (330 կբ/վ / 303 կբ/վ)"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
- <item msgid="6398189564246596868">"Օպտիմալացված ձայնի որակ համար"</item>
+ <item msgid="6398189564246596868">"Օպտիմալացված ձայնի որակի համար"</item>
<item msgid="4327143584633311908">"Ձայնի և կապի հավասարակշռված որակ"</item>
<item msgid="4681409244565426925">"Օպտիմալացված կապի որակի համար"</item>
</string-array>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 12d61fe..186b79c 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -140,10 +140,10 @@
<string name="choose_profile" msgid="8229363046053568878">"Pilih Profil"</string>
<string name="category_personal" msgid="1299663247844969448">"Pribadi"</string>
<string name="category_work" msgid="8699184680584175622">"Kantor"</string>
- <string name="development_settings_title" msgid="215179176067683667">"Opsi pengembang"</string>
- <string name="development_settings_enable" msgid="542530994778109538">"Aktifkan opsi pengembang"</string>
+ <string name="development_settings_title" msgid="215179176067683667">"Opsi developer"</string>
+ <string name="development_settings_enable" msgid="542530994778109538">"Aktifkan opsi developer"</string>
<string name="development_settings_summary" msgid="1815795401632854041">"Menyetel opsi untuk pengembangan apl"</string>
- <string name="development_settings_not_available" msgid="4308569041701535607">"Opsi pengembang tidak tersedia untuk pengguna ini"</string>
+ <string name="development_settings_not_available" msgid="4308569041701535607">"Opsi developer tidak tersedia untuk pengguna ini"</string>
<string name="vpn_settings_not_available" msgid="956841430176985598">"Setelan VPN tidak tersedia untuk pengguna ini"</string>
<string name="tethering_settings_not_available" msgid="6765770438438291012">"Setelan Penambatan tidak tersedia untuk pengguna ini"</string>
<string name="apn_settings_not_available" msgid="7873729032165324000">"Setelan Nama Titik Akses tidak tersedia untuk pengguna ini"</string>
diff --git a/packages/SettingsLib/res/values-kn/arrays.xml b/packages/SettingsLib/res/values-kn/arrays.xml
index 73851a4..c729b42 100644
--- a/packages/SettingsLib/res/values-kn/arrays.xml
+++ b/packages/SettingsLib/res/values-kn/arrays.xml
@@ -58,14 +58,22 @@
<item msgid="3878793616631049349">"DRM ವಿಷಯಗಳಿಗೆ ಮಾತ್ರ HDCP ಪರೀಕ್ಷಿಸುವಿಕೆಯನ್ನು ಬಳಸು"</item>
<item msgid="45075631231212732">"HDCP ಪರಿಶೀಲನೆಯನ್ನು ಯಾವಾಗಲೂ ಬಳಸು"</item>
</string-array>
- <!-- no translation found for bluetooth_a2dp_codec_titles:2 (686685526567131661) -->
- <!-- no translation found for bluetooth_a2dp_codec_titles:3 (8910200421843557332) -->
- <!-- no translation found for bluetooth_a2dp_codec_titles:4 (8434403964359457768) -->
- <!-- no translation found for bluetooth_a2dp_codec_titles:5 (6751080638867012696) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (6839647709301342559) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (2279916056363477395) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (6641171061200063516) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:5 (7950781694447359344) -->
+ <string-array name="bluetooth_a2dp_codec_titles">
+ <item msgid="7065842274271279580">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item>
+ <item msgid="7539690996561263909">"SBC"</item>
+ <item msgid="686685526567131661">"AAC"</item>
+ <item msgid="8910200421843557332">"aptX"</item>
+ <item msgid="8434403964359457768">"aptX HD"</item>
+ <item msgid="6751080638867012696">"LDAC"</item>
+ </string-array>
+ <string-array name="bluetooth_a2dp_codec_summaries">
+ <item msgid="5062108632402595000">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item>
+ <item msgid="6898329690939802290">"SBC"</item>
+ <item msgid="6839647709301342559">"AAC"</item>
+ <item msgid="2279916056363477395">"aptX"</item>
+ <item msgid="6641171061200063516">"aptX HD"</item>
+ <item msgid="7950781694447359344">"LDAC"</item>
+ </string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="3093023430402746802">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item>
<item msgid="8895532488906185219">"44.1 kHz"</item>
@@ -102,10 +110,16 @@
<item msgid="8900559293912978337">"ಮೊನೊ"</item>
<item msgid="8883739882299884241">"ಸ್ಟೀರಿಯೊ"</item>
</string-array>
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (7158319962230727476) -->
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (8860982705384396512) -->
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (6398189564246596868) -->
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (4681409244565426925) -->
+ <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+ <item msgid="7158319962230727476">"ಆಡಿಯೋ ಗುಣಮಟ್ಟಕ್ಕಾಗಿ (990kbps/909kbps) ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗಿದೆ"</item>
+ <item msgid="2921767058740704969">"ಸಂತುಲಿತ ಆಡಿಯೊ ಮತ್ತು ಸಂಪರ್ಕದ ಗುಣಮಟ್ಟ (660kbps/606kbps)"</item>
+ <item msgid="8860982705384396512">"ಸಂಪರ್ಕದ ಗುಣಮಟ್ಟಕ್ಕಾಗಿ (330kbps/303kbps) ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗಿದೆ"</item>
+ </string-array>
+ <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+ <item msgid="6398189564246596868">"ಆಡಿಯೊ ಗುಣಮಟ್ಟಕ್ಕಾಗಿ ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗಿದೆ"</item>
+ <item msgid="4327143584633311908">"ಸಂತುಲಿತ ಆಡಿಯೊ ಮತ್ತು ಸಂಪರ್ಕದ ಗುಣಮಟ್ಟ"</item>
+ <item msgid="4681409244565426925">"ಸಂಪರ್ಕ ಗುಣಮಟ್ಟಕ್ಕಾಗಿ ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗಿದೆ"</item>
+ </string-array>
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"ಆಫ್"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-ky/arrays.xml b/packages/SettingsLib/res/values-ky/arrays.xml
index f00ebe5..4d1a685 100644
--- a/packages/SettingsLib/res/values-ky/arrays.xml
+++ b/packages/SettingsLib/res/values-ky/arrays.xml
@@ -111,14 +111,14 @@
<item msgid="8883739882299884241">"Стерео"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
- <item msgid="7158319962230727476">"Аудио сапаты үчүн оптималдаштырылды (990кб/сек./909кб/сек.)"</item>
+ <item msgid="7158319962230727476">"Аудионун сапатын оптималдаштыруу (990кб/сек./909кб/сек.)"</item>
<item msgid="2921767058740704969">"Теңделген аудио жана туташуу сапаты (660кб/сек./606кб/сек.)"</item>
- <item msgid="8860982705384396512">"Туташуу сапаты үчүн оптималдаштырылды (330кб/сек./303кб/сек.)"</item>
+ <item msgid="8860982705384396512">"Туташуунун сапатын оптималдаштыруу (330кб/сек./303кб/сек.)"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
- <item msgid="6398189564246596868">"Аудио сапаты үчүн оптималдаштырылды"</item>
+ <item msgid="6398189564246596868">"Аудионун сапатын оптималдаштыруу"</item>
<item msgid="4327143584633311908">"Теңделген аудио жана туташуу сапаты"</item>
- <item msgid="4681409244565426925">"Туташуу сапаты үчүн оптималдаштырылды"</item>
+ <item msgid="4681409244565426925">"Туташуунун сапатын оптималдаштыруу"</item>
</string-array>
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Өчүк"</item>
diff --git a/packages/SettingsLib/res/values-ml/arrays.xml b/packages/SettingsLib/res/values-ml/arrays.xml
index bb05b8c..e79a567 100644
--- a/packages/SettingsLib/res/values-ml/arrays.xml
+++ b/packages/SettingsLib/res/values-ml/arrays.xml
@@ -58,14 +58,22 @@
<item msgid="3878793616631049349">"DRM ഉള്ളടക്കത്തിനുമാത്രമായി HDCP പരിശോധന ഉപയോഗിക്കുക"</item>
<item msgid="45075631231212732">"എല്ലായ്പ്പോഴും HDCP പരിശോധന ഉപയോഗിക്കുക"</item>
</string-array>
- <!-- no translation found for bluetooth_a2dp_codec_titles:2 (686685526567131661) -->
- <!-- no translation found for bluetooth_a2dp_codec_titles:3 (8910200421843557332) -->
- <!-- no translation found for bluetooth_a2dp_codec_titles:4 (8434403964359457768) -->
- <!-- no translation found for bluetooth_a2dp_codec_titles:5 (6751080638867012696) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (6839647709301342559) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (2279916056363477395) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (6641171061200063516) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:5 (7950781694447359344) -->
+ <string-array name="bluetooth_a2dp_codec_titles">
+ <item msgid="7065842274271279580">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ (ഡിഫോൾട്ട്)"</item>
+ <item msgid="7539690996561263909">"SBC"</item>
+ <item msgid="686685526567131661">"AAC"</item>
+ <item msgid="8910200421843557332">"aptX"</item>
+ <item msgid="8434403964359457768">"aptX HD"</item>
+ <item msgid="6751080638867012696">"LDAC"</item>
+ </string-array>
+ <string-array name="bluetooth_a2dp_codec_summaries">
+ <item msgid="5062108632402595000">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ (ഡിഫോൾട്ട്)"</item>
+ <item msgid="6898329690939802290">"SBC"</item>
+ <item msgid="6839647709301342559">"AAC"</item>
+ <item msgid="2279916056363477395">"aptX"</item>
+ <item msgid="6641171061200063516">"aptX HD"</item>
+ <item msgid="7950781694447359344">"LDAC"</item>
+ </string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="3093023430402746802">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ (ഡിഫോൾട്ട്)"</item>
<item msgid="8895532488906185219">"44.1 kHz"</item>
@@ -102,10 +110,16 @@
<item msgid="8900559293912978337">"മോണോ"</item>
<item msgid="8883739882299884241">"സ്റ്റീരിയോ"</item>
</string-array>
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (7158319962230727476) -->
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (8860982705384396512) -->
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (6398189564246596868) -->
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (4681409244565426925) -->
+ <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+ <item msgid="7158319962230727476">"ശബ്ദനിലവാരമുയർത്താൻ ഒപ്റ്റിമൈസ് ചെയ്തു (990kbps/909kbps)"</item>
+ <item msgid="2921767058740704969">"സന്തുലിതമായ ഓഡിയോ/കണക്ഷൻ നിലവാരം (660kbps/606kbps)"</item>
+ <item msgid="8860982705384396512">"കണക്ഷൻ നിലവാരമുയർത്താൻ ഒപ്റ്റിമൈസ് ചെയ്തു (330kbps/303kbps)"</item>
+ </string-array>
+ <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+ <item msgid="6398189564246596868">"ശബ്ദനിലവാരമുയർത്താൻ ഒപ്റ്റിമൈസ് ചെയ്തു"</item>
+ <item msgid="4327143584633311908">"സന്തുലിതമായ ഓഡിയോ/കണക്ഷൻ നിലവാരം"</item>
+ <item msgid="4681409244565426925">"കണക്ഷൻ നിലവാരമുയർത്താൻ ഒപ്റ്റിമൈസ് ചെയ്തു"</item>
+ </string-array>
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"ഓഫ്"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-mr/arrays.xml b/packages/SettingsLib/res/values-mr/arrays.xml
index 751b7be..e83b1f9 100644
--- a/packages/SettingsLib/res/values-mr/arrays.xml
+++ b/packages/SettingsLib/res/values-mr/arrays.xml
@@ -58,14 +58,22 @@
<item msgid="3878793616631049349">"केवळ DRM सामग्रीसाठी HDCP तपासणी वापरा"</item>
<item msgid="45075631231212732">"नेहमी HDCP तपासणी वापरा"</item>
</string-array>
- <!-- no translation found for bluetooth_a2dp_codec_titles:2 (686685526567131661) -->
- <!-- no translation found for bluetooth_a2dp_codec_titles:3 (8910200421843557332) -->
- <!-- no translation found for bluetooth_a2dp_codec_titles:4 (8434403964359457768) -->
- <!-- no translation found for bluetooth_a2dp_codec_titles:5 (6751080638867012696) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (6839647709301342559) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (2279916056363477395) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (6641171061200063516) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:5 (7950781694447359344) -->
+ <string-array name="bluetooth_a2dp_codec_titles">
+ <item msgid="7065842274271279580">"प्रणाली निवड वापरा (डीफॉल्ट)"</item>
+ <item msgid="7539690996561263909">"SBC"</item>
+ <item msgid="686685526567131661">"AAC"</item>
+ <item msgid="8910200421843557332">"aptX"</item>
+ <item msgid="8434403964359457768">"aptX HD"</item>
+ <item msgid="6751080638867012696">"LDAC"</item>
+ </string-array>
+ <string-array name="bluetooth_a2dp_codec_summaries">
+ <item msgid="5062108632402595000">"प्रणाली निवड वापरा (डीफॉल्ट)"</item>
+ <item msgid="6898329690939802290">"SBC"</item>
+ <item msgid="6839647709301342559">"AAC"</item>
+ <item msgid="2279916056363477395">"aptX"</item>
+ <item msgid="6641171061200063516">"aptX HD"</item>
+ <item msgid="7950781694447359344">"LDAC"</item>
+ </string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="3093023430402746802">"प्रणाली निवड वापरा (डीफॉल्ट)"</item>
<item msgid="8895532488906185219">"44.1 kHz"</item>
@@ -102,10 +110,16 @@
<item msgid="8900559293912978337">"मोनो"</item>
<item msgid="8883739882299884241">"स्टिरिओ"</item>
</string-array>
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (7158319962230727476) -->
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (8860982705384396512) -->
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (6398189564246596868) -->
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (4681409244565426925) -->
+ <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+ <item msgid="7158319962230727476">"ऑडिओ गुणवत्ता (990kbps/909kbps) साठी ऑप्टिमाइझ केली"</item>
+ <item msgid="2921767058740704969">"संतुलित ऑडिओ आणि कनेक्शन गुणवत्ता (660kbps/606kbps)"</item>
+ <item msgid="8860982705384396512">"कनेक्शन गुणवत्ता (330kbps/303kbps) साठी ऑप्टिमाइझ केली"</item>
+ </string-array>
+ <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+ <item msgid="6398189564246596868">"ऑडिओ गुणवत्तेसाठी ऑप्टिमाइझ केले"</item>
+ <item msgid="4327143584633311908">"संतुलित ऑडिओ आणि कनेक्शन गुणवत्ता"</item>
+ <item msgid="4681409244565426925">"कनेक्शन गुणवत्तेसाठी ऑप्टिमाइझ केले"</item>
+ </string-array>
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"बंद"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-ne/arrays.xml b/packages/SettingsLib/res/values-ne/arrays.xml
index 46a758e..cee130b 100644
--- a/packages/SettingsLib/res/values-ne/arrays.xml
+++ b/packages/SettingsLib/res/values-ne/arrays.xml
@@ -58,14 +58,22 @@
<item msgid="3878793616631049349">"DRM सामग्रीको लागि मात्र HDCP जाँचको प्रयोग गर्नुहोस्"</item>
<item msgid="45075631231212732">"सधैँ HDCP जाँच प्रयोग गर्नुहोस्"</item>
</string-array>
- <!-- no translation found for bluetooth_a2dp_codec_titles:2 (686685526567131661) -->
- <!-- no translation found for bluetooth_a2dp_codec_titles:3 (8910200421843557332) -->
- <!-- no translation found for bluetooth_a2dp_codec_titles:4 (8434403964359457768) -->
- <!-- no translation found for bluetooth_a2dp_codec_titles:5 (6751080638867012696) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (6839647709301342559) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (2279916056363477395) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (6641171061200063516) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:5 (7950781694447359344) -->
+ <string-array name="bluetooth_a2dp_codec_titles">
+ <item msgid="7065842274271279580">"प्रणालीको चयन प्रयोग गर्नुहोस् (पूर्वनिर्धारित)"</item>
+ <item msgid="7539690996561263909">"SBC"</item>
+ <item msgid="686685526567131661">"AAC"</item>
+ <item msgid="8910200421843557332">"aptX"</item>
+ <item msgid="8434403964359457768">"aptX HD"</item>
+ <item msgid="6751080638867012696">"LDAC"</item>
+ </string-array>
+ <string-array name="bluetooth_a2dp_codec_summaries">
+ <item msgid="5062108632402595000">"प्रणालीको चयन प्रयोग गर्नुहोस् (पूर्वनिर्धारित)"</item>
+ <item msgid="6898329690939802290">"SBC"</item>
+ <item msgid="6839647709301342559">"AAC"</item>
+ <item msgid="2279916056363477395">"aptX"</item>
+ <item msgid="6641171061200063516">"aptX HD"</item>
+ <item msgid="7950781694447359344">"LDAC"</item>
+ </string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="3093023430402746802">"प्रणालीको चयन प्रयोग गर्नुहोस् (पूर्वनिर्धारित)"</item>
<item msgid="8895532488906185219">"४४.१ kHz"</item>
@@ -102,10 +110,16 @@
<item msgid="8900559293912978337">"मोनो"</item>
<item msgid="8883739882299884241">"स्टेरियो"</item>
</string-array>
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (7158319962230727476) -->
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (8860982705384396512) -->
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (6398189564246596868) -->
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (4681409244565426925) -->
+ <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+ <item msgid="7158319962230727476">"अडियोको गुणस्तर सुधार्न अनुकूलन गरिएको (990kbps/909kbps)"</item>
+ <item msgid="2921767058740704969">"सन्तुलित अडियो र जडान गुणस्तर (६६०kbps/६०६kbps)"</item>
+ <item msgid="8860982705384396512">"जडानको गुणस्तर सुधार्न अनुकूलन गरिएको (330kbps/303kbps)"</item>
+ </string-array>
+ <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+ <item msgid="6398189564246596868">"अडियोको गुणस्तर सुधार्न अनुकूलन गरिएको"</item>
+ <item msgid="4327143584633311908">"सन्तुलित अडियो र जडान गुणस्तर"</item>
+ <item msgid="4681409244565426925">"जडानको गुणस्तर सुधार्न अनुकूलन गरिएको"</item>
+ </string-array>
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"निष्क्रिय गर्नुहोस्"</item>
<item msgid="1593289376502312923">"६४के"</item>
diff --git a/packages/SettingsLib/res/values-ur/arrays.xml b/packages/SettingsLib/res/values-ur/arrays.xml
index 1f94398..7ad1d17 100644
--- a/packages/SettingsLib/res/values-ur/arrays.xml
+++ b/packages/SettingsLib/res/values-ur/arrays.xml
@@ -58,14 +58,22 @@
<item msgid="3878793616631049349">"HDCP چیکنگ صرف DRM مواد کیلئے استعمال کریں"</item>
<item msgid="45075631231212732">"ہمیشہ HDCP چیکنگ استعمال کریں"</item>
</string-array>
- <!-- no translation found for bluetooth_a2dp_codec_titles:2 (686685526567131661) -->
- <!-- no translation found for bluetooth_a2dp_codec_titles:3 (8910200421843557332) -->
- <!-- no translation found for bluetooth_a2dp_codec_titles:4 (8434403964359457768) -->
- <!-- no translation found for bluetooth_a2dp_codec_titles:5 (6751080638867012696) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (6839647709301342559) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (2279916056363477395) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (6641171061200063516) -->
- <!-- no translation found for bluetooth_a2dp_codec_summaries:5 (7950781694447359344) -->
+ <string-array name="bluetooth_a2dp_codec_titles">
+ <item msgid="7065842274271279580">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item>
+ <item msgid="7539690996561263909">"SBC"</item>
+ <item msgid="686685526567131661">"AAC"</item>
+ <item msgid="8910200421843557332">"aptX"</item>
+ <item msgid="8434403964359457768">"aptX HD"</item>
+ <item msgid="6751080638867012696">"LDAC"</item>
+ </string-array>
+ <string-array name="bluetooth_a2dp_codec_summaries">
+ <item msgid="5062108632402595000">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item>
+ <item msgid="6898329690939802290">"SBC"</item>
+ <item msgid="6839647709301342559">"AAC"</item>
+ <item msgid="2279916056363477395">"aptX"</item>
+ <item msgid="6641171061200063516">"aptX HD"</item>
+ <item msgid="7950781694447359344">"LDAC"</item>
+ </string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="3093023430402746802">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item>
<item msgid="8895532488906185219">"44.1 kHz"</item>
@@ -102,10 +110,16 @@
<item msgid="8900559293912978337">"مونو"</item>
<item msgid="8883739882299884241">"اسٹیریو"</item>
</string-array>
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (7158319962230727476) -->
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (8860982705384396512) -->
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (6398189564246596868) -->
- <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (4681409244565426925) -->
+ <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+ <item msgid="7158319962230727476">"آڈیو کے معیار کیلئے بہتر بنایا گيا (990kbps/909kbps)"</item>
+ <item msgid="2921767058740704969">"متوازن آڈیو اور کنکشن کا معیار (660kbps/606kbps)"</item>
+ <item msgid="8860982705384396512">"کنکشن کے معیار کیلئے بہتر بنایا گيا (330kbps/303kbps)"</item>
+ </string-array>
+ <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+ <item msgid="6398189564246596868">"آڈیو کے معیار کیلئے بہتر بنایا گيا"</item>
+ <item msgid="4327143584633311908">"متوازن آڈیو اور کنکشن کا معیار"</item>
+ <item msgid="4681409244565426925">"کنکشن کے معیار کیلئے بہتر بنایا گيا"</item>
+ </string-array>
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"آف"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index 7bbca5e..eb64b3a 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -520,4 +520,37 @@
<item>7</item>
</integer-array>
+ <!-- BatteryMeterView parameters -->
+ <array name="batterymeter_color_levels">
+ <item>15</item>
+ <item>100</item>
+ </array>
+ <array name="batterymeter_color_values">
+ <item>@*android:color/battery_saver_mode_color</item>
+ <item>@android:color/white</item>
+ </array>
+ <array name="batterymeter_bolt_points">
+ <item>73</item> <item>0</item>
+ <item>392</item><item>0</item>
+ <item>201</item><item>259</item>
+ <item>442</item><item>259</item>
+ <item>4</item> <item>703</item>
+ <item>157</item><item>334</item>
+ <item>0</item> <item>334</item>
+ </array>
+ <array name="batterymeter_plus_points">
+ <item>3</item><item>0</item>
+ <item>5</item><item>0</item>
+ <item>5</item><item>3</item>
+ <item>8</item><item>3</item>
+ <item>8</item><item>5</item>
+ <item>5</item><item>5</item>
+ <item>5</item><item>8</item>
+ <item>3</item><item>8</item>
+ <item>3</item><item>5</item>
+ <item>0</item><item>5</item>
+ <item>0</item><item>3</item>
+ <item>3</item><item>3</item>
+ </array>
+
</resources>
diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml
index 2e8b30f..aa36617 100644
--- a/packages/SettingsLib/res/values/dimens.xml
+++ b/packages/SettingsLib/res/values/dimens.xml
@@ -57,4 +57,15 @@
<dimen name="drawer_width">300dp</dimen>
<dimen name="drawer_item_top_bottom_margin">4dp</dimen>
<dimen name="drawer_spacer_height">32dp</dimen>
+
+ <dimen name="battery_height">14.5dp</dimen>
+ <dimen name="battery_width">9.5dp</dimen>
+
+ <!-- Margin on the right side of the system icon group on Keyguard. -->
+ <fraction name="battery_button_height_fraction">10.5%</fraction>
+
+ <!-- Fraction value to smooth the edges of the battery icon. The path will be inset by this
+ fraction of a pixel.-->
+ <fraction name="battery_subpixel_smoothing_left">0%</fraction>
+ <fraction name="battery_subpixel_smoothing_right">0%</fraction>
</resources>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 0129632..5475b32 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -900,4 +900,7 @@
<string name="retail_demo_reset_next">Next</string>
<!-- Title for carrier demo mode factory reset confirmation dialog. [CHAR LIMIT=40] -->
<string name="retail_demo_reset_title">Password required</string>
+
+ <!-- Glyph to be overlaid atop the battery when the level is extremely low. Do not translate. -->
+ <string name="battery_meter_very_low_overlay_symbol">!</string>
</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index ae6ada2a..11e2a71 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -6,8 +6,8 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.UserInfo;
import android.content.pm.Signature;
+import android.content.pm.UserInfo;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.TypedArray;
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/PackageManagerWrapper.java b/packages/SettingsLib/src/com/android/settingslib/applications/PackageManagerWrapper.java
new file mode 100644
index 0000000..caa7929
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/PackageManagerWrapper.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.applications;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.graphics.drawable.Drawable;
+import android.os.UserHandle;
+
+import java.util.List;
+
+/**
+ * This interface replicates a subset of the android.content.pm.PackageManager (PM). The interface
+ * exists so that we can use a thin wrapper around the PM in production code and a mock in tests.
+ * We cannot directly mock or shadow the PM, because some of the methods we rely on are newer than
+ * the API version supported by Robolectric.
+ */
+public interface PackageManagerWrapper {
+
+ /**
+ * Returns the real {@code PackageManager} object.
+ */
+ PackageManager getPackageManager();
+
+ /**
+ * Calls {@code PackageManager.getInstalledApplicationsAsUser()}.
+ *
+ * @see android.content.pm.PackageManager#getInstalledApplicationsAsUser
+ */
+ List<ApplicationInfo> getInstalledApplicationsAsUser(int flags, int userId);
+
+ /**
+ * Calls {@code PackageManager.hasSystemFeature()}.
+ *
+ * @see android.content.pm.PackageManager#hasSystemFeature
+ */
+ boolean hasSystemFeature(String name);
+
+ /**
+ * Calls {@code PackageManager.queryIntentActivitiesAsUser()}.
+ *
+ * @see android.content.pm.PackageManager#queryIntentActivitiesAsUser
+ */
+ List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent, int flags, int userId);
+
+ /**
+ * Calls {@code PackageManager.getInstallReason()}.
+ *
+ * @see android.content.pm.PackageManager#getInstallReason
+ */
+ int getInstallReason(String packageName, UserHandle user);
+
+ /**
+ * Calls {@code PackageManager.getApplicationInfoAsUser}
+ */
+ ApplicationInfo getApplicationInfoAsUser(String packageName, int i, int userId)
+ throws PackageManager.NameNotFoundException;
+
+ /**
+ * Calls {@code PackageManager.setDefaultBrowserPackageNameAsUser}
+ */
+ boolean setDefaultBrowserPackageNameAsUser(String packageName, int userId);
+
+ /**
+ * Calls {@code PackageManager.getDefaultBrowserPackageNameAsUser}
+ */
+ String getDefaultBrowserPackageNameAsUser(int userId);
+
+ /**
+ * Calls {@code PackageManager.getHomeActivities}
+ */
+ ComponentName getHomeActivities(List<ResolveInfo> homeActivities);
+
+ /**
+ * Calls {@code PackageManager.queryIntentServicesAsUser}
+ */
+ List<ResolveInfo> queryIntentServicesAsUser(Intent intent, int i, int user);
+
+ /**
+ * Calls {@code PackageManager.replacePreferredActivity}
+ */
+ void replacePreferredActivity(IntentFilter homeFilter, int matchCategoryEmpty,
+ ComponentName[] componentNames, ComponentName component);
+
+ /**
+ * Gets information about a particular package from the package manager.
+ * @param packageName The name of the package we would like information about.
+ * @param i additional options flags. see javadoc for {@link PackageManager#getPackageInfo(String, int)}
+ * @return The PackageInfo for the requested package
+ * @throws NameNotFoundException
+ */
+ PackageInfo getPackageInfo(String packageName, int i) throws NameNotFoundException;
+
+ /**
+ * Retrieves the icon associated with this particular set of ApplicationInfo
+ * @param info The ApplicationInfo to retrieve the icon for
+ * @return The icon as a drawable.
+ */
+ Drawable getUserBadgedIcon(ApplicationInfo info);
+
+ /**
+ * Retrieves the label associated with the particular set of ApplicationInfo
+ * @param app The ApplicationInfo to retrieve the label for
+ * @return the label as a CharSequence
+ */
+ CharSequence loadLabel(ApplicationInfo app);
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/PackageManagerWrapperImpl.java b/packages/SettingsLib/src/com/android/settingslib/applications/PackageManagerWrapperImpl.java
new file mode 100644
index 0000000..9b2cd7c
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/PackageManagerWrapperImpl.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.applications;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.graphics.drawable.Drawable;
+import android.os.UserHandle;
+
+import java.util.List;
+
+/**
+ * A thin wrapper class that simplifies testing by putting a mockable layer between the application
+ * and the PackageManager. This class only provides access to the minimum number of functions from
+ * the PackageManager needed for DeletionHelper to work.
+ */
+public class PackageManagerWrapperImpl implements PackageManagerWrapper {
+
+ private final PackageManager mPm;
+
+ public PackageManagerWrapperImpl(PackageManager pm) {
+ mPm = pm;
+ }
+
+ @Override
+ public PackageManager getPackageManager() {
+ return mPm;
+ }
+
+ @Override
+ public List<ApplicationInfo> getInstalledApplicationsAsUser(int flags, int userId) {
+ return mPm.getInstalledApplicationsAsUser(flags, userId);
+ }
+
+ @Override
+ public boolean hasSystemFeature(String name) {
+ return mPm.hasSystemFeature(name);
+ }
+
+ @Override
+ public List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent, int flags, int userId) {
+ return mPm.queryIntentActivitiesAsUser(intent, flags, userId);
+ }
+
+ @Override
+ public int getInstallReason(String packageName, UserHandle user) {
+ return mPm.getInstallReason(packageName, user);
+ }
+
+ @Override
+ public ApplicationInfo getApplicationInfoAsUser(String packageName, int i, int userId)
+ throws PackageManager.NameNotFoundException {
+ return mPm.getApplicationInfoAsUser(packageName, i, userId);
+ }
+
+ @Override
+ public boolean setDefaultBrowserPackageNameAsUser(String packageName, int userId) {
+ return mPm.setDefaultBrowserPackageNameAsUser(packageName, userId);
+ }
+
+ @Override
+ public String getDefaultBrowserPackageNameAsUser(int userId) {
+ return mPm.getDefaultBrowserPackageNameAsUser(userId);
+ }
+
+ @Override
+ public ComponentName getHomeActivities(List<ResolveInfo> homeActivities) {
+ return mPm.getHomeActivities(homeActivities);
+ }
+
+ @Override
+ public List<ResolveInfo> queryIntentServicesAsUser(Intent intent, int i, int user) {
+ return mPm.queryIntentServicesAsUser(intent, i, user);
+ }
+
+ @Override
+ public void replacePreferredActivity(IntentFilter homeFilter, int matchCategoryEmpty,
+ ComponentName[] componentNames, ComponentName component) {
+ mPm.replacePreferredActivity(homeFilter, matchCategoryEmpty, componentNames, component);
+ }
+
+ @Override
+ public PackageInfo getPackageInfo(String packageName, int i) throws NameNotFoundException {
+ return mPm.getPackageInfo(packageName, i);
+ }
+
+ @Override
+ public Drawable getUserBadgedIcon(ApplicationInfo info) {
+ return mPm.getUserBadgedIcon(mPm.loadUnbadgedItemIcon(info, info),
+ new UserHandle(UserHandle.getUserId(info.uid)));
+ }
+
+ @Override
+ public CharSequence loadLabel(ApplicationInfo app) {
+ return app.loadLabel(mPm);
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java b/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java
new file mode 100644
index 0000000..acb0650
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.settingslib.applications;
+
+import android.app.usage.StorageStats;
+import android.app.usage.StorageStatsManager;
+import android.content.Context;
+import android.os.UserHandle;
+
+/**
+ * StorageStatsSource wraps the StorageStatsManager for testability purposes.
+ */
+public class StorageStatsSource {
+ private StorageStatsManager mStorageStatsManager;
+
+ public StorageStatsSource(Context context) {
+ mStorageStatsManager = context.getSystemService(StorageStatsManager.class);
+ }
+
+ public StorageStatsSource.ExternalStorageStats getExternalStorageStats(String volumeUuid, UserHandle user) {
+ return new StorageStatsSource.ExternalStorageStats(
+ mStorageStatsManager.queryExternalStatsForUser(volumeUuid, user));
+ }
+
+ public StorageStatsSource.AppStorageStats getStatsForUid(String volumeUuid, int uid) {
+ return new StorageStatsSource.AppStorageStatsImpl(mStorageStatsManager.queryStatsForUid(volumeUuid, uid));
+ }
+
+ /**
+ * Static class that provides methods for querying the amount of external storage available as
+ * well as breaking it up into several media types.
+ */
+ public static class ExternalStorageStats {
+ public long totalBytes;
+ public long audioBytes;
+ public long videoBytes;
+ public long imageBytes;
+
+ /**
+ * Convenience method for testing.
+ */
+ public ExternalStorageStats(long totalBytes, long audioBytes, long videoBytes,
+ long imageBytes) {
+ this.totalBytes = totalBytes;
+ this.audioBytes = audioBytes;
+ this.videoBytes = videoBytes;
+ this.imageBytes = imageBytes;
+ }
+
+ /**
+ * Creates an ExternalStorageStats from the system version of ExternalStorageStats. They are
+ * identical other than the utility method created for test purposes.
+ * @param stats The stats to copy to wrap.
+ */
+ public ExternalStorageStats(android.app.usage.ExternalStorageStats stats) {
+ totalBytes = stats.getTotalBytes();
+ audioBytes = stats.getAudioBytes();
+ videoBytes = stats.getVideoBytes();
+ imageBytes = stats.getImageBytes();
+ }
+ }
+
+ /**
+ * Interface that exists to simplify testing. The platform {@link StorageStats} is too new and
+ * robolectric cannot see it. It simply wraps a StorageStats object and forwards method calls
+ * to the real object
+ */
+ public interface AppStorageStats {
+ long getCodeBytes();
+ long getDataBytes();
+ long getCacheBytes();
+ long getTotalBytes();
+ }
+
+ /**
+ * Simple implementation of AppStorageStats that will allow you to query the StorageStats object
+ * passed in for storage information about an app.
+ */
+ public static class AppStorageStatsImpl implements
+ StorageStatsSource.AppStorageStats {
+ private StorageStats mStats;
+
+ public AppStorageStatsImpl(StorageStats stats) {
+ mStats = stats;
+ }
+
+ public long getCodeBytes() {
+ return mStats.getCodeBytes();
+ }
+
+ public long getDataBytes() {
+ return mStats.getDataBytes();
+ }
+
+ public long getCacheBytes() {
+ return mStats.getCacheBytes();
+ }
+
+ public long getTotalBytes() {
+ return mStats.getCacheBytes() + mStats.getCodeBytes() + mStats.getDataBytes();
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
index 32478a7..7f469b5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
@@ -34,6 +34,7 @@
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import com.android.settingslib.R;
@@ -273,6 +274,11 @@
super.invalidateSelf();
}
+ @Override
+ public ConstantState getConstantState() {
+ return new BitmapDrawable(mBitmap).getConstantState();
+ }
+
/**
* This 'bakes' the current state of this icon into a bitmap and removes/recycles the source
* bitmap/drawable. Use this when no more changes will be made and an intrinsic size is set.
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
new file mode 100755
index 0000000..fd2e7ca
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
@@ -0,0 +1,465 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.graph;
+
+import android.animation.ArgbEvaluator;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.RectF;
+import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
+import android.provider.Settings;
+import com.android.settingslib.R;
+import com.android.settingslib.Utils;
+
+public class BatteryMeterDrawableBase extends Drawable {
+
+ private static final float ASPECT_RATIO = 9.5f / 14.5f;
+ public static final String TAG = BatteryMeterDrawableBase.class.getSimpleName();
+
+ protected final Context mContext;
+
+ private int mLevel = -1;
+ private boolean mPluggedIn;
+ private boolean mPowerSaveEnabled;
+ private boolean mShowPercent;
+
+ private static final boolean SINGLE_DIGIT_PERCENT = false;
+
+ private static final int FULL = 96;
+
+ private static final float BOLT_LEVEL_THRESHOLD = 0.3f; // opaque bolt below this fraction
+
+ private final int[] mColors;
+ private final int mIntrinsicWidth;
+ private final int mIntrinsicHeight;
+
+ private float mButtonHeightFraction;
+ private float mSubpixelSmoothingLeft;
+ private float mSubpixelSmoothingRight;
+ private final Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint, mBoltPaint,
+ mPlusPaint;
+ private float mTextHeight, mWarningTextHeight;
+ private int mIconTint = Color.WHITE;
+ private float mOldDarkIntensity = 0f;
+
+ private int mHeight;
+ private int mWidth;
+ private String mWarningString;
+ private final int mCriticalLevel;
+ private int mChargeColor;
+ private final float[] mBoltPoints;
+ private final Path mBoltPath = new Path();
+ private final float[] mPlusPoints;
+ private final Path mPlusPath = new Path();
+
+ private final RectF mFrame = new RectF();
+ private final RectF mButtonFrame = new RectF();
+ private final RectF mBoltFrame = new RectF();
+ private final RectF mPlusFrame = new RectF();
+
+ private final Path mShapePath = new Path();
+ private final Path mClipPath = new Path();
+ private final Path mTextPath = new Path();
+
+ private int mDarkModeBackgroundColor;
+ private int mDarkModeFillColor;
+
+ private int mLightModeBackgroundColor;
+ private int mLightModeFillColor;
+
+ public BatteryMeterDrawableBase(Context context, int frameColor) {
+ mContext = context;
+ final Resources res = context.getResources();
+ TypedArray levels = res.obtainTypedArray(R.array.batterymeter_color_levels);
+ TypedArray colors = res.obtainTypedArray(R.array.batterymeter_color_values);
+
+ final int N = levels.length();
+ mColors = new int[2 * N];
+ for (int i = 0; i < N; i++) {
+ mColors[2 * i] = levels.getInt(i, 0);
+ mColors[2 * i + 1] = colors.getColor(i, 0);
+ }
+ levels.recycle();
+ colors.recycle();
+
+ mWarningString = context.getString(R.string.battery_meter_very_low_overlay_symbol);
+ mCriticalLevel = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_criticalBatteryWarningLevel);
+ mButtonHeightFraction = context.getResources().getFraction(
+ R.fraction.battery_button_height_fraction, 1, 1);
+ mSubpixelSmoothingLeft = context.getResources().getFraction(
+ R.fraction.battery_subpixel_smoothing_left, 1, 1);
+ mSubpixelSmoothingRight = context.getResources().getFraction(
+ R.fraction.battery_subpixel_smoothing_right, 1, 1);
+
+ mFramePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mFramePaint.setColor(frameColor);
+ mFramePaint.setDither(true);
+ mFramePaint.setStrokeWidth(0);
+ mFramePaint.setStyle(Paint.Style.FILL_AND_STROKE);
+
+ mBatteryPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mBatteryPaint.setDither(true);
+ mBatteryPaint.setStrokeWidth(0);
+ mBatteryPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+
+ mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ Typeface font = Typeface.create("sans-serif-condensed", Typeface.BOLD);
+ mTextPaint.setTypeface(font);
+ mTextPaint.setTextAlign(Paint.Align.CENTER);
+
+ mWarningTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ font = Typeface.create("sans-serif", Typeface.BOLD);
+ mWarningTextPaint.setTypeface(font);
+ mWarningTextPaint.setTextAlign(Paint.Align.CENTER);
+ if (mColors.length > 1) {
+ mWarningTextPaint.setColor(mColors[1]);
+ }
+
+ mChargeColor = Utils.getDefaultColor(mContext, R.color.batterymeter_charge_color);
+
+ mBoltPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mBoltPaint.setColor(Utils.getDefaultColor(mContext, R.color.batterymeter_bolt_color));
+ mBoltPoints = loadPoints(res, R.array.batterymeter_bolt_points);
+
+ mPlusPaint = new Paint(mBoltPaint);
+ mPlusPoints = loadPoints(res, R.array.batterymeter_plus_points);
+
+ mDarkModeBackgroundColor =
+ Utils.getDefaultColor(mContext, R.color.dark_mode_icon_color_dual_tone_background);
+ mDarkModeFillColor =
+ Utils.getDefaultColor(mContext, R.color.dark_mode_icon_color_dual_tone_fill);
+ mLightModeBackgroundColor =
+ Utils.getDefaultColor(mContext, R.color.light_mode_icon_color_dual_tone_background);
+ mLightModeFillColor =
+ Utils.getDefaultColor(mContext, R.color.light_mode_icon_color_dual_tone_fill);
+
+ mIntrinsicWidth = context.getResources().getDimensionPixelSize(R.dimen.battery_width);
+ mIntrinsicHeight = context.getResources().getDimensionPixelSize(R.dimen.battery_height);
+ }
+
+ @Override
+ public int getIntrinsicHeight() {
+ return mIntrinsicHeight;
+ }
+
+ @Override
+ public int getIntrinsicWidth() {
+ return mIntrinsicWidth;
+ }
+
+ public void setShowPercent(boolean show) {
+ mShowPercent = show;
+ postInvalidate();
+ }
+
+ public void setPluggedIn(boolean val) {
+ mPluggedIn = val;
+ postInvalidate();
+ }
+
+ public void setBatteryLevel(int val) {
+ mLevel = val;
+ postInvalidate();
+ }
+
+ public void setPowerSave(boolean val) {
+ mPowerSaveEnabled = val;
+ postInvalidate();
+ }
+
+ // an approximation of View.postInvalidate()
+ protected void postInvalidate() {
+ unscheduleSelf(this::invalidateSelf);
+ scheduleSelf(this::invalidateSelf, 0);
+ }
+
+ private static float[] loadPoints(Resources res, int pointArrayRes) {
+ final int[] pts = res.getIntArray(pointArrayRes);
+ int maxX = 0, maxY = 0;
+ for (int i = 0; i < pts.length; i += 2) {
+ maxX = Math.max(maxX, pts[i]);
+ maxY = Math.max(maxY, pts[i + 1]);
+ }
+ final float[] ptsF = new float[pts.length];
+ for (int i = 0; i < pts.length; i += 2) {
+ ptsF[i] = (float) pts[i] / maxX;
+ ptsF[i + 1] = (float) pts[i + 1] / maxY;
+ }
+ return ptsF;
+ }
+
+ @Override
+ public void setBounds(int left, int top, int right, int bottom) {
+ super.setBounds(left, top, right, bottom);
+ mHeight = bottom - top;
+ mWidth = right - left;
+ mWarningTextPaint.setTextSize(mHeight * 0.75f);
+ mWarningTextHeight = -mWarningTextPaint.getFontMetrics().ascent;
+ }
+
+ private int getColorForLevel(int percent) {
+ // If we are in power save mode, always use the normal color.
+ if (mPowerSaveEnabled) {
+ return mColors[mColors.length - 1];
+ }
+ int thresh, color = 0;
+ for (int i = 0; i < mColors.length; i += 2) {
+ thresh = mColors[i];
+ color = mColors[i + 1];
+ if (percent <= thresh) {
+
+ // Respect tinting for "normal" level
+ if (i == mColors.length - 2) {
+ return mIconTint;
+ } else {
+ return color;
+ }
+ }
+ }
+ return color;
+ }
+
+ public void setDarkIntensity(float darkIntensity) {
+ if (darkIntensity == mOldDarkIntensity) {
+ return;
+ }
+ int backgroundColor = getBackgroundColor(darkIntensity);
+ int fillColor = getFillColor(darkIntensity);
+ setColors(fillColor, backgroundColor);
+ mOldDarkIntensity = darkIntensity;
+ }
+
+ public void setColors(int fillColor, int backgroundColor) {
+ mIconTint = fillColor;
+ mFramePaint.setColor(backgroundColor);
+ mBoltPaint.setColor(fillColor);
+ mChargeColor = fillColor;
+ invalidateSelf();
+ }
+
+ private int getBackgroundColor(float darkIntensity) {
+ return getColorForDarkIntensity(
+ darkIntensity, mLightModeBackgroundColor, mDarkModeBackgroundColor);
+ }
+
+ private int getFillColor(float darkIntensity) {
+ return getColorForDarkIntensity(
+ darkIntensity, mLightModeFillColor, mDarkModeFillColor);
+ }
+
+ private int getColorForDarkIntensity(float darkIntensity, int lightColor, int darkColor) {
+ return (int) ArgbEvaluator.getInstance().evaluate(darkIntensity, lightColor, darkColor);
+ }
+
+ @Override
+ public void draw(Canvas c) {
+ final int level = mLevel;
+
+ if (level == -1) return;
+
+ float drawFrac = (float) level / 100f;
+ final int height = mHeight;
+ final int width = (int) (ASPECT_RATIO * mHeight);
+ int px = (mWidth - width) / 2;
+
+ final int buttonHeight = (int) (height * mButtonHeightFraction);
+
+ mFrame.set(0, 0, width, height);
+ mFrame.offset(px, 0);
+
+ // button-frame: area above the battery body
+ mButtonFrame.set(
+ mFrame.left + Math.round(width * 0.25f),
+ mFrame.top,
+ mFrame.right - Math.round(width * 0.25f),
+ mFrame.top + buttonHeight);
+
+ mButtonFrame.top += mSubpixelSmoothingLeft;
+ mButtonFrame.left += mSubpixelSmoothingLeft;
+ mButtonFrame.right -= mSubpixelSmoothingRight;
+
+ // frame: battery body area
+ mFrame.top += buttonHeight;
+ mFrame.left += mSubpixelSmoothingLeft;
+ mFrame.top += mSubpixelSmoothingLeft;
+ mFrame.right -= mSubpixelSmoothingRight;
+ mFrame.bottom -= mSubpixelSmoothingRight;
+
+ // set the battery charging color
+ mBatteryPaint.setColor(mPluggedIn ? mChargeColor : getColorForLevel(level));
+
+ if (level >= FULL) {
+ drawFrac = 1f;
+ } else if (level <= mCriticalLevel) {
+ drawFrac = 0f;
+ }
+
+ final float levelTop = drawFrac == 1f ? mButtonFrame.top
+ : (mFrame.top + (mFrame.height() * (1f - drawFrac)));
+
+ // define the battery shape
+ mShapePath.reset();
+ mShapePath.moveTo(mButtonFrame.left, mButtonFrame.top);
+ mShapePath.lineTo(mButtonFrame.right, mButtonFrame.top);
+ mShapePath.lineTo(mButtonFrame.right, mFrame.top);
+ mShapePath.lineTo(mFrame.right, mFrame.top);
+ mShapePath.lineTo(mFrame.right, mFrame.bottom);
+ mShapePath.lineTo(mFrame.left, mFrame.bottom);
+ mShapePath.lineTo(mFrame.left, mFrame.top);
+ mShapePath.lineTo(mButtonFrame.left, mFrame.top);
+ mShapePath.lineTo(mButtonFrame.left, mButtonFrame.top);
+
+ if (mPluggedIn) {
+ // define the bolt shape
+ final float bl = mFrame.left + mFrame.width() / 4f;
+ final float bt = mFrame.top + mFrame.height() / 6f;
+ final float br = mFrame.right - mFrame.width() / 4f;
+ final float bb = mFrame.bottom - mFrame.height() / 10f;
+ if (mBoltFrame.left != bl || mBoltFrame.top != bt
+ || mBoltFrame.right != br || mBoltFrame.bottom != bb) {
+ mBoltFrame.set(bl, bt, br, bb);
+ mBoltPath.reset();
+ mBoltPath.moveTo(
+ mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(),
+ mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height());
+ for (int i = 2; i < mBoltPoints.length; i += 2) {
+ mBoltPath.lineTo(
+ mBoltFrame.left + mBoltPoints[i] * mBoltFrame.width(),
+ mBoltFrame.top + mBoltPoints[i + 1] * mBoltFrame.height());
+ }
+ mBoltPath.lineTo(
+ mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(),
+ mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height());
+ }
+
+ float boltPct = (mBoltFrame.bottom - levelTop) / (mBoltFrame.bottom - mBoltFrame.top);
+ boltPct = Math.min(Math.max(boltPct, 0), 1);
+ if (boltPct <= BOLT_LEVEL_THRESHOLD) {
+ // draw the bolt if opaque
+ c.drawPath(mBoltPath, mBoltPaint);
+ } else {
+ // otherwise cut the bolt out of the overall shape
+ mShapePath.op(mBoltPath, Path.Op.DIFFERENCE);
+ }
+ } else if (mPowerSaveEnabled) {
+ // define the plus shape
+ final float pw = mFrame.width() * 2 / 3;
+ final float pl = mFrame.left + (mFrame.width() - pw) / 2;
+ final float pt = mFrame.top + (mFrame.height() - pw) / 2;
+ final float pr = mFrame.right - (mFrame.width() - pw) / 2;
+ final float pb = mFrame.bottom - (mFrame.height() - pw) / 2;
+ if (mPlusFrame.left != pl || mPlusFrame.top != pt
+ || mPlusFrame.right != pr || mPlusFrame.bottom != pb) {
+ mPlusFrame.set(pl, pt, pr, pb);
+ mPlusPath.reset();
+ mPlusPath.moveTo(
+ mPlusFrame.left + mPlusPoints[0] * mPlusFrame.width(),
+ mPlusFrame.top + mPlusPoints[1] * mPlusFrame.height());
+ for (int i = 2; i < mPlusPoints.length; i += 2) {
+ mPlusPath.lineTo(
+ mPlusFrame.left + mPlusPoints[i] * mPlusFrame.width(),
+ mPlusFrame.top + mPlusPoints[i + 1] * mPlusFrame.height());
+ }
+ mPlusPath.lineTo(
+ mPlusFrame.left + mPlusPoints[0] * mPlusFrame.width(),
+ mPlusFrame.top + mPlusPoints[1] * mPlusFrame.height());
+ }
+
+ float boltPct = (mPlusFrame.bottom - levelTop) / (mPlusFrame.bottom - mPlusFrame.top);
+ boltPct = Math.min(Math.max(boltPct, 0), 1);
+ if (boltPct <= BOLT_LEVEL_THRESHOLD) {
+ // draw the bolt if opaque
+ c.drawPath(mPlusPath, mPlusPaint);
+ } else {
+ // otherwise cut the bolt out of the overall shape
+ mShapePath.op(mPlusPath, Path.Op.DIFFERENCE);
+ }
+ }
+
+ // compute percentage text
+ boolean pctOpaque = false;
+ float pctX = 0, pctY = 0;
+ String pctText = null;
+ if (!mPluggedIn && !mPowerSaveEnabled && level > mCriticalLevel && mShowPercent) {
+ mTextPaint.setColor(getColorForLevel(level));
+ mTextPaint.setTextSize(height *
+ (SINGLE_DIGIT_PERCENT ? 0.75f
+ : (mLevel == 100 ? 0.38f : 0.5f)));
+ mTextHeight = -mTextPaint.getFontMetrics().ascent;
+ pctText = String.valueOf(SINGLE_DIGIT_PERCENT ? (level / 10) : level);
+ pctX = mWidth * 0.5f;
+ pctY = (mHeight + mTextHeight) * 0.47f;
+ pctOpaque = levelTop > pctY;
+ if (!pctOpaque) {
+ mTextPath.reset();
+ mTextPaint.getTextPath(pctText, 0, pctText.length(), pctX, pctY, mTextPath);
+ // cut the percentage text out of the overall shape
+ mShapePath.op(mTextPath, Path.Op.DIFFERENCE);
+ }
+ }
+
+ // draw the battery shape background
+ c.drawPath(mShapePath, mFramePaint);
+
+ // draw the battery shape, clipped to charging level
+ mFrame.top = levelTop;
+ mClipPath.reset();
+ mClipPath.addRect(mFrame, Path.Direction.CCW);
+ mShapePath.op(mClipPath, Path.Op.INTERSECT);
+ c.drawPath(mShapePath, mBatteryPaint);
+
+ if (!mPluggedIn && !mPowerSaveEnabled) {
+ if (level <= mCriticalLevel) {
+ // draw the warning text
+ final float x = mWidth * 0.5f;
+ final float y = (mHeight + mWarningTextHeight) * 0.48f;
+ c.drawText(mWarningString, x, y, mWarningTextPaint);
+ } else if (pctOpaque) {
+ // draw the percentage text
+ c.drawText(pctText, pctX, pctY, mTextPaint);
+ }
+ }
+ }
+
+ // Some stuff required by Drawable.
+ @Override
+ public void setAlpha(int alpha) {
+ }
+
+ @Override
+ public void setColorFilter(@Nullable ColorFilter colorFilter) {
+ mFramePaint.setColorFilter(colorFilter);
+ mBatteryPaint.setColorFilter(colorFilter);
+ mWarningTextPaint.setColorFilter(colorFilter);
+ mBoltPaint.setColorFilter(colorFilter);
+ mPlusPaint.setColorFilter(colorFilter);
+ }
+
+ @Override
+ public int getOpacity() {
+ return 0;
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index c617994..0ec16ae2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -41,7 +41,6 @@
import android.os.Looper;
import android.os.Message;
import android.provider.Settings;
-import android.support.annotation.WorkerThread;
import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
@@ -211,7 +210,7 @@
mNetworkScoreManager = networkScoreManager;
- mScoreCache = new WifiNetworkScoreCache(context, new CacheListener(mWorkHandler) {
+ mScoreCache = new WifiNetworkScoreCache(context, new CacheListener(mMainHandler) {
@Override
public void networkCacheUpdated(List<ScoredNetwork> networks) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
@@ -282,12 +281,7 @@
* then forceUpdate() must be called to populate getAccessPoints().
*/
public void startTracking() {
- mWorkHandler.post(new Runnable() {
- @Override
- public void run() {
- registerScoreCache();
- }
- });
+ registerScoreCache();
mContext.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(Settings.Global.NETWORK_SCORING_UI_ENABLED),
@@ -305,7 +299,6 @@
}
}
- @WorkerThread
private void registerScoreCache() {
mNetworkScoreManager.registerNetworkScoreCache(
NetworkKey.TYPE_WIFI,
@@ -341,20 +334,17 @@
}
pauseScanning();
- mWorkHandler.post(new Runnable() {
- @Override
- public void run() {
- unregisterAndClearScoreCache();
- }
- });
+ unregisterAndClearScoreCache();
+
mContext.getContentResolver().unregisterContentObserver(mObserver);
}
- @WorkerThread
private void unregisterAndClearScoreCache() {
- mRequestedScores.clear();
mNetworkScoreManager.unregisterNetworkScoreCache(NetworkKey.TYPE_WIFI, mScoreCache);
mScoreCache.clearScores();
+
+ // Clear the scores on the work handler to avoid concurrent modification exceptions
+ mWorkHandler.post(() -> mRequestedScores.clear());
}
/**
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
new file mode 100644
index 0000000..4de2c12
--- /dev/null
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
@@ -0,0 +1,71 @@
+package com.android.settingslib.graph;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import com.android.settingslib.R;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyFloat;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class BatteryMeterDrawableBaseTest {
+ private Context mContext;
+ private Resources mResources;
+ private BatteryMeterDrawableBase mBatteryDrawable;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getTargetContext();
+ mResources = mContext.getResources();
+ mBatteryDrawable = new BatteryMeterDrawableBase(mContext, 0);
+ }
+
+ @Test
+ public void testGetIntrinsicSize() {
+ assertThat(mBatteryDrawable.getIntrinsicWidth()).
+ isEqualTo(mResources.getDimensionPixelSize(R.dimen.battery_width));
+ assertThat(mBatteryDrawable.getIntrinsicHeight()).
+ isEqualTo(mResources.getDimensionPixelSize(R.dimen.battery_height));
+ }
+
+ @Test
+ public void testDrawNothingBeforeOnBatteryLevelChanged() {
+ final Canvas canvas = mock(Canvas.class);
+ mBatteryDrawable.draw(canvas);
+ verify(canvas, never()).drawPath(any(), any());
+ verify(canvas, never()).drawText(anyString(), anyFloat(), anyFloat(), any());
+ }
+
+ @Test
+ public void testDrawingForTypicalValues() {
+ final Canvas canvas = mock(Canvas.class);
+ final int levels[] = { 0, 1, 5, 10, 25, 50, 75, 90, 95, 99, 100 };
+ final boolean bools[] = { false, true };
+ for (int l : levels) {
+ for (boolean plugged : bools) {
+ for (boolean saver : bools) {
+ for (boolean percent : bools) {
+ mBatteryDrawable.setBatteryLevel(l);
+ mBatteryDrawable.setPowerSave(saver);
+ mBatteryDrawable.setPluggedIn(plugged);
+ mBatteryDrawable.setShowPercent(percent);
+ mBatteryDrawable.draw(canvas);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index 08736c7..0f220aa 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -72,7 +72,7 @@
public class WifiTrackerTest {
private static final String TAG = "WifiTrackerTest";
- private static final int LATCH_TIMEOUT = 2000;
+ private static final int LATCH_TIMEOUT = 4000;
private static final String SSID_1 = "ssid1";
private static final String BSSID_1 = "00:00:00:00:00:00";
@@ -226,7 +226,7 @@
mAccessPointsChangedLatch = new CountDownLatch(1);
sendScanResultsAndProcess(tracker);
- mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
+ assertTrue(mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
return tracker;
}
@@ -242,7 +242,8 @@
true,
mockWifiManager,
mockConnectivityManager,
- mockNetworkScoreManager, mMainLooper
+ mockNetworkScoreManager,
+ mMainLooper
);
return tracker;
@@ -257,7 +258,7 @@
latch.countDown();
}
});
- latch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
+ assertTrue("Latch timed out", latch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
}
private void sendScanResultsAndProcess(WifiTracker tracker) throws InterruptedException {
@@ -265,7 +266,8 @@
Intent i = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
tracker.mReceiver.onReceive(mContext, i);
- mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
+ assertTrue("Latch timed out",
+ mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
}
private void updateScores() {
@@ -348,7 +350,7 @@
// Test unregister
tracker.stopTracking();
- latch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
+ assertTrue("Latch timed out", latch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
verify(mockNetworkScoreManager)
.unregisterNetworkScoreCache(NetworkKey.TYPE_WIFI, scoreCache);
}
@@ -359,12 +361,15 @@
WifiTracker tracker = createTrackerAndInjectInitialScanResults();
tracker.stopTracking();
+ android.util.Log.d("WifiTrackerTest", "Clearing previously captured requested keys");
mRequestedKeys.clear();
- mRequestScoresLatch = new CountDownLatch(2);
+ mRequestScoresLatch = new CountDownLatch(1);
startTracking(tracker);
- mRequestScoresLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
+ assertTrue("Latch timed out",
+ mRequestScoresLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
+ android.util.Log.d("WifiTrackerTest", "requested keys: " + mRequestedKeys);
assertTrue(mRequestedKeys.contains(NETWORK_KEY_1));
assertTrue(mRequestedKeys.contains(NETWORK_KEY_2));
}
@@ -379,6 +384,8 @@
}
private void updateScoresAndWaitForAccessPointsChangedCallback() throws InterruptedException {
+ // Updating scores can happen together or one after the other, so the latch countdown is set
+ // to 2.
mAccessPointsChangedLatch = new CountDownLatch(2);
updateScores();
mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
@@ -462,6 +469,8 @@
@Test
public void scoresShouldBeRequestedForNewScanResultOnly() throws InterruptedException {
+ // Scores can be requested together or serially depending on how the scan results are
+ // processed.
mRequestScoresLatch = new CountDownLatch(2);
WifiTracker tracker = createTrackerAndInjectInitialScanResults();
mRequestScoresLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
@@ -484,9 +493,24 @@
mRequestScoresLatch = new CountDownLatch(1);
sendScanResultsAndProcess(tracker);
- mRequestScoresLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
+ assertTrue(mRequestScoresLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
assertEquals(1, mRequestedKeys.size());
assertTrue(mRequestedKeys.contains(new NetworkKey(new WifiKey('"' + ssid + '"', bssid))));
}
+
+ @Test
+ public void scoreCacheAndListenerShouldBeUnregisteredWhenStopTrackingIsCalled() throws Exception
+ {
+ WifiTracker tracker = createTrackerAndInjectInitialScanResults();
+ WifiNetworkScoreCache cache = mScoreCacheCaptor.getValue();
+
+ tracker.stopTracking();
+ verify(mockNetworkScoreManager).unregisterNetworkScoreCache(NetworkKey.TYPE_WIFI, cache);
+
+ // Verify listener is unregistered so updating a score does not throw an error by posting
+ // a message to the dead work handler
+ mWorkerThread.quit();
+ updateScores();
+ }
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SuggestionParserTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SuggestionParserTest.java
index 0032cf0..7729dec 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SuggestionParserTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SuggestionParserTest.java
@@ -16,39 +16,35 @@
package com.android.settingslib;
-import android.util.Log;
-import android.content.Context;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
-import android.os.Bundle;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.os.Bundle;
import android.preference.PreferenceManager;
+import com.android.settingslib.drawer.Tile;
+import com.android.settingslib.drawer.TileUtilsTest;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
-import com.android.settingslib.drawer.Tile;
-import com.android.settingslib.drawer.TileUtilsTest;
-
import java.util.ArrayList;
import java.util.List;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
-import org.robolectric.RuntimeEnvironment;
-
@RunWith(SettingLibRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class SuggestionParserTest {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawable/UserIconDrawableTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawable/UserIconDrawableTest.java
new file mode 100644
index 0000000..a21390a
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawable/UserIconDrawableTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.drawable;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+
+import com.android.settingslib.R;
+import com.android.settingslib.SettingLibRobolectricTestRunner;
+import com.android.settingslib.TestConfig;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import static com.google.common.truth.Truth.assertThat;
+
+@RunWith(SettingLibRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class UserIconDrawableTest {
+
+ private UserIconDrawable mDrawable;
+
+ @Test
+ public void getConstantState_shouldNotBeNull() {
+ final Bitmap b = BitmapFactory.decodeResource(
+ RuntimeEnvironment.application.getResources(),
+ R.drawable.home);
+ mDrawable = new UserIconDrawable(100 /* size */).setIcon(b).bake();
+
+ assertThat(mDrawable.getConstantState()).isNotNull();
+ }
+}
diff --git a/packages/SystemUI/plugin/Android.mk b/packages/SystemUI/plugin/Android.mk
index 86527db..05ee6b2 100644
--- a/packages/SystemUI/plugin/Android.mk
+++ b/packages/SystemUI/plugin/Android.mk
@@ -27,3 +27,13 @@
LOCAL_JAR_EXCLUDE_FILES := none
include $(BUILD_STATIC_JAVA_LIBRARY)
+
+include $(CLEAR_VARS)
+
+# Dummy to generate .toc files.
+LOCAL_PACKAGE_NAME := PluginDummyLib
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := SystemUIPluginLib
+
+include $(BUILD_PACKAGE)
diff --git a/packages/SystemUI/plugin/ExamplePlugin/src/com/android/systemui/plugin/testoverlayplugin/SampleOverlayPlugin.java b/packages/SystemUI/plugin/ExamplePlugin/src/com/android/systemui/plugin/testoverlayplugin/SampleOverlayPlugin.java
index a2f84dc7..13fc76c 100644
--- a/packages/SystemUI/plugin/ExamplePlugin/src/com/android/systemui/plugin/testoverlayplugin/SampleOverlayPlugin.java
+++ b/packages/SystemUI/plugin/ExamplePlugin/src/com/android/systemui/plugin/testoverlayplugin/SampleOverlayPlugin.java
@@ -15,11 +15,14 @@
package com.android.systemui.plugin.testoverlayplugin;
import android.content.Context;
+import android.graphics.Rect;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewTreeObserver.InternalInsetsInfo;
+import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
import com.android.systemui.plugins.OverlayPlugin;
public class SampleOverlayPlugin implements OverlayPlugin {
@@ -28,6 +31,9 @@
private View mStatusBarView;
private View mNavBarView;
+ private boolean mInputSetup;
+ private boolean mCollapseDesired;
+ private float mStatusBarHeight;
@Override
public int getVersion() {
@@ -43,6 +49,10 @@
@Override
public void onDestroy() {
+ if (mInputSetup) {
+ mStatusBarView.getViewTreeObserver().removeOnComputeInternalInsetsListener(
+ onComputeInternalInsetsListener);
+ }
Log.d(TAG, "onDestroy");
if (mStatusBarView != null) {
mStatusBarView.post(
@@ -57,6 +67,9 @@
public void setup(View statusBar, View navBar) {
Log.d(TAG, "Setup");
+ int id = mPluginContext.getResources().getIdentifier("status_bar_height", "dimen",
+ "android");
+ mStatusBarHeight = mPluginContext.getResources().getDimension(id);
if (statusBar instanceof ViewGroup) {
mStatusBarView = LayoutInflater.from(mPluginContext)
.inflate(R.layout.colored_overlay, (ViewGroup) statusBar, false);
@@ -68,4 +81,28 @@
((ViewGroup) navBar).addView(mNavBarView);
}
}
+
+ @Override
+ public void setCollapseDesired(boolean collapseDesired) {
+ mCollapseDesired = collapseDesired;
+ }
+
+ @Override
+ public boolean holdStatusBarOpen() {
+ if (!mInputSetup) {
+ mInputSetup = true;
+ mStatusBarView.getViewTreeObserver().addOnComputeInternalInsetsListener(
+ onComputeInternalInsetsListener);
+ }
+ return true;
+ }
+
+ final OnComputeInternalInsetsListener onComputeInternalInsetsListener = inoutInfo -> {
+ inoutInfo.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
+ if (mCollapseDesired) {
+ inoutInfo.touchableRegion.set(new Rect(0, 0, 50000, (int) mStatusBarHeight));
+ } else {
+ inoutInfo.touchableRegion.set(new Rect(0, 0, 50000, 50000));
+ }
+ };
}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/OverlayPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/OverlayPlugin.java
index 91a2604..f5074f7 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/OverlayPlugin.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/OverlayPlugin.java
@@ -21,4 +21,14 @@
int VERSION = 1;
void setup(View statusBar, View navBar);
+
+ default boolean holdStatusBarOpen() {
+ return false;
+ }
+
+ /**
+ * Only called if the plugin has returned true to holdStatusBarOpen().
+ */
+ default void setCollapseDesired(boolean collapseDesired) {
+ }
}
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index 63af3e0..c6452c0 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -21,6 +21,8 @@
<com.android.systemui.statusbar.phone.PhoneStatusBarView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/status_bar_height"
android:id="@+id/status_bar"
android:background="@drawable/system_bar_background"
android:orientation="vertical"
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index c2686f8..51eefb6 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -59,9 +59,10 @@
sysui:ignoreRightInset="true"
android:importantForAccessibility="no"/>
- <include layout="@layout/status_bar"
+ <FrameLayout
+ android:id="@+id/status_bar_container"
android:layout_width="match_parent"
- android:layout_height="@dimen/status_bar_height" />
+ android:layout_height="wrap_content" />
<include layout="@layout/brightness_mirror" />
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index e491257..e647ade 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Bladsy <xliff:g id="ID_1">%1$d</xliff:g> van <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Vou uit"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimeer"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Maak toe"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Foon raak warm"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Sommige kenmerke is beperk terwyl foon afkoel"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Jou foon sal outomaties probeer om af te koel. Jy kan steeds jou foon gebruik, maar dit sal dalk stadiger wees.\n\nJou foon sal normaalweg werk nadat dit afgekoel het."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Aanporboodskap vir wagwoord"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Opletberigte"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Skermkiekies"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Sekuriteit"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Gebruikerstatus"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Algemene boodskappe"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Berging"</string>
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index d1aefcf..392cd01 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"ገጽ <xliff:g id="ID_1">%1$d</xliff:g> ከ <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"ዘርጋ"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"አሳንስ"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"አሰናብት"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"ስልኩ እየሞቀ ነው"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"ስልኩ እየቀዘቀዘ ሳለ አንዳንድ ባህሪዎች ይገደባሉ"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"የእርስዎ ስልክ በራስ-ሰር ለመቀዝቀዝ ይሞክራል። አሁንም ስልክዎን መጠቀም ይችላሉ፣ ነገር ግን ሊንቀራፈፍ ይችላል።\n\nአንዴ ስልክዎ ከቀዘቀዘ በኋላ በመደበኝነት ያሄዳል።"</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"የይለፍ ቃል ጠይቅ"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"ማንቂያዎች"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"ቅጽበታዊ ገጽ እይታዎች"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"ደህንነት"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"የተጠቃሚ ሁኔታ"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"አጠቃላይ መልዕክቶች"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"ማከማቻ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 77da13c..f9073f5 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -679,7 +679,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"الصفحة <xliff:g id="ID_1">%1$d</xliff:g> من <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"توسيع"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"تصغير"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"تجاهل"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"تزداد درجة حرارة الهاتف"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"يتم تقييد عمل بعض الميزات إلى أن تنخفض درجة حرارة الهاتف"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"سيحاول الهاتف تخفيض درجة حرارته تلقائيًا. سيظل بإمكانك استخدام هاتفك، ولكن قد يعمل بشكل أبطأ.\n\nبعد أن تنخفض درجة حرارة الهاتف، سيستعيد سرعته المعتادة."</string>
@@ -690,7 +691,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"طلب إدخال كلمة المرور"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"التنبيهات"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"لقطات الشاشة"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"الأمان"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"حالة المستخدمين"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"رسائل عامة"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"سعة التخزين"</string>
</resources>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index c55e94c..ba67b3a 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> səhifədən <xliff:g id="ID_1">%1$d</xliff:g> səhifə"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Genişləndirin"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Kiçildin"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Yığışdırın"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Telefon qızmağa başlayır"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Telefon soyuyana kimi bəzi funksiyalar məhdudlaşdırılır"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefonunuz avtomatik olaraq soyumağa başlayacaq. Telefon istifadəsinə davam edə bilərsiniz, lakin sürəti yavaşlaya bilər.\n\nTelefonunuz soyuduqdan sonra normal işləyəcək."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Parol üçün bildiriş"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Siqnallar"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Skrinşotlar"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Təhlükəsizlik"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"İstifadəçi statusu"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Ümumi Mesajlar"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Yaddaş"</string>
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index cc5ab4c..2e01995 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -673,7 +673,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>. strana od <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Proširi"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Umanji"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Odbaci"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Telefon se zagrejao"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Neke funkcije su ograničene dok se telefon ne ohladi"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefon će automatski pokušati da se ohladi. I dalje ćete moći da koristite telefon, ali će sporije reagovati.\n\nKada se telefon ohladi, normalno će raditi."</string>
@@ -684,7 +685,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Upit za lozinku"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Obaveštenja"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Snimci ekrana"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Bezbednost"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Status korisnika"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Opšte poruke"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Memorijski prostor"</string>
</resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index d084152..60f042e 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -677,7 +677,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Старонка <xliff:g id="ID_1">%1$d</xliff:g> з <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Разгарнуць"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Згарнуць"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Адхіліць"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Тэлефон награваецца"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Некаторыя функцыі абмежаваны, пакуль тэлефон астывае"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Ваш тэлефон аўтаматычна паспрабуе астыць. Вы можаце па-ранейшаму карыстацца сваім тэлефонам, але ён можа працаваць больш павольна.\n\nПасля таго як ваш тэлефон астыне, ён будзе працаваць у звычайным рэжыме."</string>
@@ -688,7 +689,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Запыт пароля"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Абвесткi"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Здымкі экрана"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Бяспека"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Статус карыстальніка"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Агульныя паведамленні"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Захоўванне"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 08a8142..2ebac75 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Страница <xliff:g id="ID_1">%1$d</xliff:g> от <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Разгъване"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Намаляване"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Отхвърляне"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Телефонът загрява"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Някои функции са ограничени, докато телефонът се охлажда"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Телефонът ви автоматично ще направи опит за охлаждане. Пак можете да го използвате, но той може да работи по-бавно.\n\nСлед като се охлади, ще работи нормално."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Подкана за парола"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Сигнали"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Екранни снимки"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Сигурност"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Състояние на потребителя"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Общи съобщения"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Хранилище"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 90aa1f5..ed86d3d 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -156,7 +156,7 @@
<string name="accessibility_cell_data_off" msgid="8000803571751407635">"সেলুলার ডেটা বন্ধ আছে"</string>
<string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"ব্লুটুথ টিথারিং৷"</string>
<string name="accessibility_airplane_mode" msgid="834748999790763092">"বিমান মোড৷"</string>
- <string name="accessibility_no_sims" msgid="3957997018324995781">"কোনো SIM কার্ড নেই।"</string>
+ <string name="accessibility_no_sims" msgid="3957997018324995781">"কোনো সিম কার্ড নেই।"</string>
<string name="accessibility_carrier_network_change_mode" msgid="4017301580441304305">"পরিষেবা প্রদানকারীর নেটওয়ার্ক পরিবর্তিত হচ্ছে।"</string>
<string name="accessibility_battery_details" msgid="7645516654955025422">"ব্যাটারির বিশদ বিবরণ খুলুন"</string>
<string name="accessibility_battery_level" msgid="7451474187113371965">"<xliff:g id="NUMBER">%d</xliff:g> শতাংশ ব্যাটারি রয়েছে৷"</string>
@@ -526,24 +526,15 @@
<string name="notification_importance_high" msgid="3316555356062640222">"শব্দ করে ও স্ক্রীনে ভেসে ওঠে"</string>
<string name="notification_more_settings" msgid="816306283396553571">"আরো সেটিংস"</string>
<string name="notification_done" msgid="5279426047273930175">"সম্পন্ন"</string>
- <!-- no translation found for notification_menu_accessibility (2046162834248888553) -->
- <skip />
- <!-- no translation found for notification_menu_gear_description (2204480013726775108) -->
- <skip />
- <!-- no translation found for notification_menu_snooze_description (3653669438131034525) -->
- <skip />
- <!-- no translation found for snooze_option_15_min (1068727451405610715) -->
- <skip />
- <!-- no translation found for snooze_option_30_min (867081342535195788) -->
- <skip />
- <!-- no translation found for snooze_option_1_hour (1098086401880077154) -->
- <skip />
- <!-- no translation found for snooze_option_dont_snooze (655446566007801922) -->
- <skip />
- <!-- no translation found for snooze_undo (6074877317002985129) -->
- <skip />
- <!-- no translation found for snoozed_for_time (2390718332980204462) -->
- <skip />
+ <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
+ <string name="notification_menu_gear_description" msgid="2204480013726775108">"বিজ্ঞপ্তির নিয়ন্ত্রণগুলি"</string>
+ <string name="notification_menu_snooze_description" msgid="3653669438131034525">"বিজ্ঞপ্তি মনে করিয়ে দেওয়ার বিকল্পগুলি"</string>
+ <string name="snooze_option_15_min" msgid="1068727451405610715">"১৫ মিনিট"</string>
+ <string name="snooze_option_30_min" msgid="867081342535195788">"৩০ মিনিট"</string>
+ <string name="snooze_option_1_hour" msgid="1098086401880077154">"১ ঘণ্টা"</string>
+ <string name="snooze_option_dont_snooze" msgid="655446566007801922">"মনে করানো হবে না"</string>
+ <string name="snooze_undo" msgid="6074877317002985129">"পূর্বাবস্থায় ফিরুন"</string>
+ <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> পরে আবার মনে করানো হবে"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"ব্যাটারির ব্যবহার"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"চার্জ করার সময় ব্যাটারি সেভার উপলব্ধ নয়"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"ব্যাটারি সেভার"</string>
@@ -605,24 +596,23 @@
<string name="switch_bar_on" msgid="1142437840752794229">"চালু আছে"</string>
<string name="switch_bar_off" msgid="8803270596930432874">"বন্ধ আছে"</string>
<string name="nav_bar" msgid="1993221402773877607">"নেভিগেশন দন্ড"</string>
- <!-- no translation found for nav_bar_layout (3664072994198772020) -->
- <skip />
- <!-- no translation found for nav_bar_left (731491280511316123) -->
- <skip />
- <!-- no translation found for nav_bar_right (2523774879720231974) -->
- <skip />
- <!-- no translation found for nav_bar_button_type (6947806619897153791) -->
- <skip />
- <!-- no translation found for nav_bar_default (8587114043070993007) -->
- <skip />
- <!-- no translation found for nav_bar_buttons:0 (1545641631806817203) -->
- <!-- no translation found for nav_bar_buttons:1 (5742013440802239414) -->
- <!-- no translation found for nav_bar_buttons:2 (8748101184830239843) -->
- <!-- no translation found for nav_bar_buttons:3 (8175437057325747277) -->
- <!-- no translation found for nav_bar_layouts:0 (4967898371682516967) -->
- <!-- no translation found for nav_bar_layouts:1 (6210279084134579668) -->
- <!-- no translation found for nav_bar_layouts:2 (89143234390889289) -->
- <!-- no translation found for nav_bar_layouts:3 (7715533883382410603) -->
+ <string name="nav_bar_layout" msgid="3664072994198772020">"লেআউট"</string>
+ <string name="nav_bar_left" msgid="731491280511316123">"বাঁ"</string>
+ <string name="nav_bar_right" msgid="2523774879720231974">"ডান"</string>
+ <string name="nav_bar_button_type" msgid="6947806619897153791">"বোতামের ধরণ"</string>
+ <string name="nav_bar_default" msgid="8587114043070993007">"(ডিফল্ট)"</string>
+ <string-array name="nav_bar_buttons">
+ <item msgid="1545641631806817203">"ক্লিপবোর্ড"</item>
+ <item msgid="5742013440802239414">"কীকোড"</item>
+ <item msgid="8748101184830239843">"মেনু / কীবোর্ড স্যুইচার"</item>
+ <item msgid="8175437057325747277">"কোনো কিছুই নয়"</item>
+ </string-array>
+ <string-array name="nav_bar_layouts">
+ <item msgid="4967898371682516967">"ভাগ করা (ডিফল্ট)"</item>
+ <item msgid="6210279084134579668">"কেন্দ্রস্থ"</item>
+ <item msgid="89143234390889289">"বাঁ দিকে সারিবদ্ধ"</item>
+ <item msgid="7715533883382410603">"ডান দিকে সারিবদ্ধ"</item>
+ </string-array>
<string name="menu_ime" msgid="4943221416525250684">"মেনু / কীবোর্ড স্যুইচার"</string>
<string name="save" msgid="2311877285724540644">"সংরক্ষণ করুন"</string>
<string name="reset" msgid="2448168080964209908">"পুনরায় সেট করুন"</string>
@@ -630,8 +620,7 @@
<string name="clipboard" msgid="1313879395099896312">"ক্লিপবোর্ড"</string>
<string name="accessibility_key" msgid="5701989859305675896">"কাস্টম নেভিগেশান বোতাম"</string>
<string name="keycode" msgid="7335281375728356499">"কীকোড"</string>
- <!-- no translation found for icon (8732339849035837289) -->
- <skip />
+ <string name="icon" msgid="8732339849035837289">"আইকন"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"টাইলগুলি যোগ করার জন্য টেনে আনুন"</string>
<string name="drag_to_remove_tiles" msgid="3361212377437088062">"সরানোর জন্য এখানে টেনে আনুন"</string>
<string name="qs_edit" msgid="2232596095725105230">"সম্পাদনা করুন"</string>
@@ -682,28 +671,18 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g>টির মধ্যে <xliff:g id="ID_1">%1$d</xliff:g> নং পৃষ্ঠা"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"প্রসারিত করুন"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"ছোটো করুন"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"খারিজ করুন"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"ফোনটি গরম হচ্ছে"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"ফোনটি ঠান্ডা হওয়ার সময় কিছু বৈশিষ্ট্য সীমিত হতে পারে"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"আপনার ফোনটি নিজে থেকেই ঠান্ডা হওয়ার চেষ্টা করবে৷ আপনি তবুও আপনার ফোন ব্যবহার করতে পারেন, কিন্তু এটি একটু ধীরে চলতে পারে৷\n\nআপনার ফোনটি পুরোপুরি ঠান্ডা হয়ে গেলে এটি স্বাভাবিকভাবে চলবে৷"</string>
- <!-- no translation found for lockscreen_left (6806490081187499505) -->
- <skip />
- <!-- no translation found for lockscreen_right (6093496261656102989) -->
- <skip />
- <!-- no translation found for lockscreen_customize (1288691376862981950) -->
- <skip />
- <!-- no translation found for lockscreen_shortcut (3734369277470360642) -->
- <skip />
- <!-- no translation found for lockscreen_unlock (4934466194763269051) -->
- <skip />
- <!-- no translation found for notification_channel_alerts (4496839309318519037) -->
- <skip />
- <!-- no translation found for notification_channel_screenshot (6314080179230000938) -->
- <skip />
- <!-- no translation found for notification_channel_security (7345516133431326347) -->
- <skip />
- <!-- no translation found for notification_channel_user_status (1436913581465146650) -->
- <skip />
- <!-- no translation found for notification_channel_storage (3077205683020695313) -->
- <skip />
+ <string name="lockscreen_left" msgid="6806490081187499505">"বাঁ"</string>
+ <string name="lockscreen_right" msgid="6093496261656102989">"ডান"</string>
+ <string name="lockscreen_customize" msgid="1288691376862981950">"কাস্টমাইজ করার শর্টকাট"</string>
+ <string name="lockscreen_shortcut" msgid="3734369277470360642">"শর্টকাট"</string>
+ <string name="lockscreen_unlock" msgid="4934466194763269051">"পাসওয়ার্ড জানতে চান"</string>
+ <string name="notification_channel_alerts" msgid="4496839309318519037">"সতর্কতাগুলি"</string>
+ <string name="notification_channel_screenshot" msgid="6314080179230000938">"স্ক্রীনশটস"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"সাধারণ বার্তাগুলি"</string>
+ <string name="notification_channel_storage" msgid="3077205683020695313">"সঞ্চয়স্থান"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index e44e4bb..d17775c 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -448,7 +448,7 @@
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Skupi"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Ekran je prikačen"</string>
<string name="screen_pinning_description" msgid="8909878447196419623">"Ekran ostaje prikazan ovako dok ga ne otkačite. Da ga otkačite, dodirnite i držite dugme Nazad."</string>
- <string name="screen_pinning_description_accessible" msgid="426190689254018656">"Ekran ostaje prikzan ovako dok ga ne otkačite. Da ga otkačite, dodirnite i držite dugme Pregled."</string>
+ <string name="screen_pinning_description_accessible" msgid="426190689254018656">"Ekran ostaje prikazan ovako dok ga ne otkačite. Da ga otkačite, dodirnite i držite dugme Pregled."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Jasno mi je"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Ne, hvala"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Želite li sakriti <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -608,7 +608,7 @@
<string-array name="nav_bar_buttons">
<item msgid="1545641631806817203">"Međumemorija"</item>
<item msgid="5742013440802239414">"Kôd tipke"</item>
- <item msgid="8748101184830239843">"Meni / Prebacivač tastature"</item>
+ <item msgid="8748101184830239843">"Prebacivač Meni / Tastatura"</item>
<item msgid="8175437057325747277">"Nema"</item>
</string-array>
<string-array name="nav_bar_layouts">
@@ -675,7 +675,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Stranica <xliff:g id="ID_1">%1$d</xliff:g> od <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Proširi"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Umanji"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Odbaci"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Telefon se pregrijava"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Neke funkcije su ograničene dok se telefon hladi"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Vaš telefon će se automatski pokušati ohladiti. I dalje možete koristi telefon, ali će možda raditi sporije.\n\nNakon što se ohladi, telefon će normalno raditi."</string>
@@ -686,7 +687,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Traži lozinku"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Upozorenja"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Snimci ekrana"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Sigurnost"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Status korisnika"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Općenite poruke"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Pohrana"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index b5cf3e4..009942c 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Pàgina <xliff:g id="ID_1">%1$d</xliff:g> (<xliff:g id="ID_2">%2$d</xliff:g> en total)"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Desplega"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimitza"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Ignora"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"El telèfon s\'està escalfant"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Algunes funcions estaran limitades mentre el telèfon es refreda"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"El telèfon provarà de refredar-se automàticament. Podràs continuar utilitzant-lo, però és possible que funcioni més lentament.\n\nUn cop s\'hagi refredat, funcionarà amb normalitat."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Sol·licita la contrasenya"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alertes"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Captures de pantalla"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Seguretat"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Estat de l\'usuari"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Missatges generals"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Emmagatzematge"</string>
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index f9ec15e..dc3df04 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -677,7 +677,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Stránka <xliff:g id="ID_1">%1$d</xliff:g> z <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Rozbalit"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimalizovat"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Zrušit"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Telefon se zahřívá"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Některé funkce jsou při chladnutí omezeny"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefon se automaticky pokusí vychladnout. Lze jej nadále používat, ale může být pomalejší.\n\nAž telefon vychladne, bude fungovat normálně."</string>
@@ -688,7 +689,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Výzva k zadání hesla"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Upozornění"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Snímky obrazovek"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Zabezpečení"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Status uživatele"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Všeobecné zprávy"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Úložiště"</string>
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 206478c..dda65e2 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Side <xliff:g id="ID_1">%1$d</xliff:g> af <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Udvid"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimer"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Afvis"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Telefonen er ved at blive varm"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Nogle funktioner er begrænsede, mens telefonen køler ned"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Din telefon forsøger automatisk at køle ned. Du kan stadig bruge telefonen, men den kører muligvis langsommere.\n\nNår din telefon er kølet ned, fungerer den normalt igen."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Spørg om adgangskode"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Underretninger"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Sikkerhed"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Brugerstatus"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Generelle meddelelser"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Lagerplads"</string>
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index a317fa06..5509a57 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -673,7 +673,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Seite <xliff:g id="ID_1">%1$d</xliff:g> von <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Maximieren"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimieren"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Schließen"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Smartphone wird warm"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Einige Funktionen sind während der Abkühlphase des Smartphones eingeschränkt"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Dein Smartphone kühlt sich automatisch ab. Du kannst dein Smartphone weiterhin nutzen, aber es reagiert möglicherweise langsamer.\n\nSobald dein Smartphone abgekühlt ist, funktioniert es wieder normal."</string>
@@ -684,7 +685,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Zur Passworteingabe auffordern"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Warnmeldungen"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Sicherheit"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Nutzerstatus"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Nachrichten"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Speicher"</string>
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 08c5822..1de2dae 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Σελίδα <xliff:g id="ID_1">%1$d</xliff:g> από <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Ανάπτυξη"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Ελαχιστοποίηση"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Παράβλεψη"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Αύξηση θερμοκρασίας τηλεφώνου"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Ορισμένες λειτουργίες περιορίζονται κατά τη μείωση της θερμοκρασίας"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Το τηλέφωνό σας θα προσπαθήσει να μειώσει αυτόματα τη θερμοκρασία. Μπορείτε να εξακολουθήσετε να το χρησιμοποιείτε, αλλά είναι πιθανό να λειτουργεί πιο αργά.\n\nΜόλις μειωθεί η θερμοκρασία του τηλεφώνου σας, θα λειτουργεί ξανά κανονικά."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Προτροπή για κωδικό πρόσβασης"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Ειδοποιήσεις"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Στιγμιότυπα οθόνης"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Ασφάλεια"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Κατάσταση χρήστη"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Γενικά μηνύματα"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Αποθηκευτικός χώρος"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 822c2df..a79caad 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Page <xliff:g id="ID_1">%1$d</xliff:g> of <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Expand"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimise"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Dismiss"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Phone is getting warm"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Some features limited while phone cools down"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Your phone will automatically try to cool down. You can still use your phone, but it may run more slowly.\n\nOnce your phone has cooled down, it will run normally."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Prompt for password"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alerts"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Security"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"User status"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"General Messages"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Storage"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 822c2df..a79caad 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Page <xliff:g id="ID_1">%1$d</xliff:g> of <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Expand"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimise"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Dismiss"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Phone is getting warm"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Some features limited while phone cools down"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Your phone will automatically try to cool down. You can still use your phone, but it may run more slowly.\n\nOnce your phone has cooled down, it will run normally."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Prompt for password"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alerts"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Security"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"User status"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"General Messages"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Storage"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 822c2df..a79caad 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Page <xliff:g id="ID_1">%1$d</xliff:g> of <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Expand"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimise"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Dismiss"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Phone is getting warm"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Some features limited while phone cools down"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Your phone will automatically try to cool down. You can still use your phone, but it may run more slowly.\n\nOnce your phone has cooled down, it will run normally."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Prompt for password"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alerts"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Security"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"User status"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"General Messages"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Storage"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 37019b1..1c4d42a 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -673,7 +673,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Expandir"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Descartar"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"El teléfono se está calentando"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Se limitarán algunas funciones mientras se enfría el teléfono"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Tu teléfono intentará enfriarse automáticamente. Podrás usarlo, pero es posible que funcione más lento.\n\nUna vez que se haya enfriado, volverá a funcionar correctamente."</string>
@@ -684,7 +685,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Solicitar contraseña"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de pantalla"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Seguridad"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Estado del usuario"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Mensajes generales"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Almacenamiento"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 75cd169..28299b7 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -528,24 +528,15 @@
<string name="notification_importance_high" msgid="3316555356062640222">"Emitir sonido y mostrar en pantalla"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Más ajustes"</string>
<string name="notification_done" msgid="5279426047273930175">"Listo"</string>
- <!-- no translation found for notification_menu_accessibility (2046162834248888553) -->
- <skip />
- <!-- no translation found for notification_menu_gear_description (2204480013726775108) -->
- <skip />
- <!-- no translation found for notification_menu_snooze_description (3653669438131034525) -->
- <skip />
- <!-- no translation found for snooze_option_15_min (1068727451405610715) -->
- <skip />
- <!-- no translation found for snooze_option_30_min (867081342535195788) -->
- <skip />
- <!-- no translation found for snooze_option_1_hour (1098086401880077154) -->
- <skip />
- <!-- no translation found for snooze_option_dont_snooze (655446566007801922) -->
- <skip />
- <!-- no translation found for snooze_undo (6074877317002985129) -->
- <skip />
- <!-- no translation found for snoozed_for_time (2390718332980204462) -->
- <skip />
+ <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="notification_menu_gear_description" msgid="2204480013726775108">"Controles de las notificaciones"</string>
+ <string name="notification_menu_snooze_description" msgid="3653669438131034525">"Opciones para posponer las notificaciones"</string>
+ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutos"</string>
+ <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutos"</string>
+ <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hora"</string>
+ <string name="snooze_option_dont_snooze" msgid="655446566007801922">"No posponer"</string>
+ <string name="snooze_undo" msgid="6074877317002985129">"DESHACER"</string>
+ <string name="snoozed_for_time" msgid="2390718332980204462">"Volverá a mostrarse en <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Uso de la batería"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Ahorro de batería no disponible mientras se carga el dispositivo"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Ahorro de batería"</string>
@@ -607,24 +598,23 @@
<string name="switch_bar_on" msgid="1142437840752794229">"Sí"</string>
<string name="switch_bar_off" msgid="8803270596930432874">"No"</string>
<string name="nav_bar" msgid="1993221402773877607">"Barra de navegación"</string>
- <!-- no translation found for nav_bar_layout (3664072994198772020) -->
- <skip />
- <!-- no translation found for nav_bar_left (731491280511316123) -->
- <skip />
- <!-- no translation found for nav_bar_right (2523774879720231974) -->
- <skip />
- <!-- no translation found for nav_bar_button_type (6947806619897153791) -->
- <skip />
- <!-- no translation found for nav_bar_default (8587114043070993007) -->
- <skip />
- <!-- no translation found for nav_bar_buttons:0 (1545641631806817203) -->
- <!-- no translation found for nav_bar_buttons:1 (5742013440802239414) -->
- <!-- no translation found for nav_bar_buttons:2 (8748101184830239843) -->
- <!-- no translation found for nav_bar_buttons:3 (8175437057325747277) -->
- <!-- no translation found for nav_bar_layouts:0 (4967898371682516967) -->
- <!-- no translation found for nav_bar_layouts:1 (6210279084134579668) -->
- <!-- no translation found for nav_bar_layouts:2 (89143234390889289) -->
- <!-- no translation found for nav_bar_layouts:3 (7715533883382410603) -->
+ <string name="nav_bar_layout" msgid="3664072994198772020">"Diseño"</string>
+ <string name="nav_bar_left" msgid="731491280511316123">"Izquierda"</string>
+ <string name="nav_bar_right" msgid="2523774879720231974">"Derecha"</string>
+ <string name="nav_bar_button_type" msgid="6947806619897153791">"Tipo de botón"</string>
+ <string name="nav_bar_default" msgid="8587114043070993007">"(predeterminada)"</string>
+ <string-array name="nav_bar_buttons">
+ <item msgid="1545641631806817203">"Portapapeles"</item>
+ <item msgid="5742013440802239414">"Código de teclado"</item>
+ <item msgid="8748101184830239843">"Menú/Cambio de teclado"</item>
+ <item msgid="8175437057325747277">"Ninguno"</item>
+ </string-array>
+ <string-array name="nav_bar_layouts">
+ <item msgid="4967898371682516967">"Dividida (predeterminada)"</item>
+ <item msgid="6210279084134579668">"Centrada"</item>
+ <item msgid="89143234390889289">"Alineada a la izquierda"</item>
+ <item msgid="7715533883382410603">"Alineada a la derecha"</item>
+ </string-array>
<string name="menu_ime" msgid="4943221416525250684">"Menú/Cambio de teclado"</string>
<string name="save" msgid="2311877285724540644">"Guardar"</string>
<string name="reset" msgid="2448168080964209908">"Restablecer"</string>
@@ -632,8 +622,7 @@
<string name="clipboard" msgid="1313879395099896312">"Portapapeles"</string>
<string name="accessibility_key" msgid="5701989859305675896">"Botón de navegación personalizada"</string>
<string name="keycode" msgid="7335281375728356499">"Código de teclado"</string>
- <!-- no translation found for icon (8732339849035837289) -->
- <skip />
+ <string name="icon" msgid="8732339849035837289">"Icono"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Arrastra para añadir funciones"</string>
<string name="drag_to_remove_tiles" msgid="3361212377437088062">"Arrastra aquí para quitar una función"</string>
<string name="qs_edit" msgid="2232596095725105230">"Editar"</string>
@@ -684,28 +673,18 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Mostrar"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Rechazar"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"El teléfono se está calentando"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Se limitan algunas funciones mientras el teléfono se enfría"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"El teléfono intentará enfriarse. Puedes seguir utilizándolo, pero es posible que funcione con mayor lentitud.\n\nUna vez que se haya enfriado, funcionará con normalidad."</string>
- <!-- no translation found for lockscreen_left (6806490081187499505) -->
- <skip />
- <!-- no translation found for lockscreen_right (6093496261656102989) -->
- <skip />
- <!-- no translation found for lockscreen_customize (1288691376862981950) -->
- <skip />
- <!-- no translation found for lockscreen_shortcut (3734369277470360642) -->
- <skip />
- <!-- no translation found for lockscreen_unlock (4934466194763269051) -->
- <skip />
- <!-- no translation found for notification_channel_alerts (4496839309318519037) -->
- <skip />
- <!-- no translation found for notification_channel_screenshot (6314080179230000938) -->
- <skip />
- <!-- no translation found for notification_channel_security (7345516133431326347) -->
- <skip />
- <!-- no translation found for notification_channel_user_status (1436913581465146650) -->
- <skip />
- <!-- no translation found for notification_channel_storage (3077205683020695313) -->
- <skip />
+ <string name="lockscreen_left" msgid="6806490081187499505">"Izquierda"</string>
+ <string name="lockscreen_right" msgid="6093496261656102989">"Derecha"</string>
+ <string name="lockscreen_customize" msgid="1288691376862981950">"Personalizar el acceso directo"</string>
+ <string name="lockscreen_shortcut" msgid="3734369277470360642">"Acceso directo"</string>
+ <string name="lockscreen_unlock" msgid="4934466194763269051">"Solicitar contraseña"</string>
+ <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
+ <string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de pantalla"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Mensajes generales"</string>
+ <string name="notification_channel_storage" msgid="3077205683020695313">"Almacenamiento"</string>
</resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 03613bd..9a888c5 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -673,7 +673,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Leht <xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Laiendamine"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimeeri"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Loobu"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Telefon soojeneb"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Mõned funktsioonid on piiratud, kuni telefon jahtub"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Teie telefon proovib automaatselt maha jahtuda. Saate telefoni ikka kasutada, kuid see võib olla aeglasem.\n\nKui telefon on jahtunud, töötab see tavapäraselt."</string>
@@ -684,7 +685,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Parooli viip"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Teatised"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Ekraanipildid"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Turvalisus"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Kasutaja olek"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Üldised sõnumid"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Salvestusruum"</string>
</resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 115c848..45ec067 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -673,7 +673,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g> orria"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Zabaldu"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizatu"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Baztertu"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Berotzen ari da telefonoa"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Eginbide batzuk ezingo dira erabili telefonoa hoztu arte"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefonoa automatikoki saiatuko da hozten. Hoztu bitartean, telefonoa erabiltzen jarrai dezakezu, baina mantsoago funtziona lezake.\n\nTelefonoaren tenperatura jaitsi bezain laster, ohi bezala funtzionatzen jarraituko du."</string>
@@ -681,10 +682,9 @@
<string name="lockscreen_right" msgid="6093496261656102989">"Eskuinaldea"</string>
<string name="lockscreen_customize" msgid="1288691376862981950">"Pertsonalizatu lasterbidea"</string>
<string name="lockscreen_shortcut" msgid="3734369277470360642">"Lasterbidea"</string>
- <string name="lockscreen_unlock" msgid="4934466194763269051">"Eskatu pasahizta"</string>
+ <string name="lockscreen_unlock" msgid="4934466194763269051">"Eskatu pasahitza"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Abisuak"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Pantaila-argazkiak"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Segurtasuna"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Erabiltzailearen egoera"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Mezu orokorrak"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Memoria"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 78af4b8..cd125b5 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"صفحه <xliff:g id="ID_1">%1$d</xliff:g> از <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"بزرگ کردن"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"کوچک کردن"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"نپذیرفتن"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"تلفن درحال گرم شدن است"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"وقتی تلفن درحال خنک شدن است، بعضی از قابلیتها محدود میشوند"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"تلفنتان بهطور خودکار سعی میکند خنک شود. همچنان میتوانید از تلفنتان استفاده کنید، اما ممکن است کندتر عمل کند.\n\nوقتی تلفن خنک شد، عملکرد عادیاش از سرگرفته میشود."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"درخواست وارد کردن گذرواژه"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"هشدارها"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"عکسهای صفحهنمایش"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"امنیت"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"وضعیت کاربر"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"پیامهای عمومی"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"فضای ذخیرهسازی"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index bc840a8..623ee51 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Sivu <xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Laajenna"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Pienennä"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Ohita"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Puhelin lämpenee"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Joidenkin ominaisuuksien käyttöä on rajoitettu puhelimen jäähtymisen aikana."</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Puhelimesi yrittää automaattisesti jäähdyttää itsensä. Voit silti käyttää puhelinta, mutta se voi toimia hitaammin.\n\nKun puhelin on jäähtynyt, se toimii normaalisti."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Kysy salasanaa"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Ilmoitukset"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Kuvakaappaukset"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Tietosuoja"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Käyttäjätila"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Yleiset viestit"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Tallennustila"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index f69a85b..5d4867c 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -673,7 +673,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Page <xliff:g id="ID_1">%1$d</xliff:g> sur <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Développer"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Réduire"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Ignorer"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Le téléphone commence à chauffer"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Les fonctionnalités sont limitées pendant que le téléphone refroidit"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Votre téléphone va essayer de se refroidir automatiquement. Vous pouvez toujours l\'utiliser, mais il risque d\'être plus lent.\n\nUne fois refroidi, il fonctionnera normalement."</string>
@@ -684,7 +685,7 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Demander le mot de passe"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alertes"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Saisies d\'écran"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Sécurité"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"État de l\'utilisateur"</string>
+ <!-- no translation found for notification_channel_general (4525309436693914482) -->
+ <skip />
<string name="notification_channel_storage" msgid="3077205683020695313">"Stockage"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 4a2f23f..97748a2 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -673,7 +673,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Page <xliff:g id="ID_1">%1$d</xliff:g> sur <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Développer"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Réduire"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Ignorer"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Le téléphone chauffe"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Fonctionnalités limitées pendant le refroidissement du téléphone"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Votre téléphone va essayer de se refroidir automatiquement. Vous pouvez toujours l\'utiliser, mais il risque d\'être plus lent.\n\nUne fois refroidi, il fonctionnera normalement."</string>
@@ -684,7 +685,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Demander le mot de passe"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alertes"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Captures d\'écran"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Sécurité"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"État de l\'utilisateur"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Nouveaux messages"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Espace de stockage"</string>
</resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index e65f3b0..5821bb9 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -673,7 +673,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Páxina <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Despregar"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Ignorar"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"O teléfono está quentando"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"O uso dalgunhas funcións é limitado mentres o teléfono arrefría"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"O teléfono tentará arrefriar automaticamente. Podes utilizalo, pero é probable que funcione máis lento.\n\nUnha vez que arrefríe, funcionará con normalidade."</string>
@@ -684,7 +685,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Solicitude de contrasinal"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de pantalla"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Seguranza"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Estado do usuario"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Mensaxes xerais"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Almacenamento"</string>
</resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index b120c7d..5fedb2d 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -526,24 +526,15 @@
<string name="notification_importance_high" msgid="3316555356062640222">"અવાજ કરો અને સ્ક્રીન પર બતાવો"</string>
<string name="notification_more_settings" msgid="816306283396553571">"વધુ સેટિંગ્સ"</string>
<string name="notification_done" msgid="5279426047273930175">"થઈ ગયું"</string>
- <!-- no translation found for notification_menu_accessibility (2046162834248888553) -->
- <skip />
- <!-- no translation found for notification_menu_gear_description (2204480013726775108) -->
- <skip />
- <!-- no translation found for notification_menu_snooze_description (3653669438131034525) -->
- <skip />
- <!-- no translation found for snooze_option_15_min (1068727451405610715) -->
- <skip />
- <!-- no translation found for snooze_option_30_min (867081342535195788) -->
- <skip />
- <!-- no translation found for snooze_option_1_hour (1098086401880077154) -->
- <skip />
- <!-- no translation found for snooze_option_dont_snooze (655446566007801922) -->
- <skip />
- <!-- no translation found for snooze_undo (6074877317002985129) -->
- <skip />
- <!-- no translation found for snoozed_for_time (2390718332980204462) -->
- <skip />
+ <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
+ <string name="notification_menu_gear_description" msgid="2204480013726775108">"સૂચના નિયંત્રણો"</string>
+ <string name="notification_menu_snooze_description" msgid="3653669438131034525">"સૂચના સ્નૂઝ કરવાના વિકલ્પો"</string>
+ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 મિનિટ"</string>
+ <string name="snooze_option_30_min" msgid="867081342535195788">"30 મિનિટ"</string>
+ <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 કલાક"</string>
+ <string name="snooze_option_dont_snooze" msgid="655446566007801922">"સ્નૂઝ કરશો નહીં"</string>
+ <string name="snooze_undo" msgid="6074877317002985129">"પૂર્વવત્ કરો"</string>
+ <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> માટે સ્નૂઝ કરો"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"બૅટરી વપરાશ"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"ચાર્જિંગ દરમિયાન બૅટરી બચતકર્તા ઉપલબ્ધ નથી"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"બૅટરી બચતકર્તા"</string>
@@ -605,24 +596,23 @@
<string name="switch_bar_on" msgid="1142437840752794229">"ચાલુ"</string>
<string name="switch_bar_off" msgid="8803270596930432874">"બંધ"</string>
<string name="nav_bar" msgid="1993221402773877607">"નેવિગેશન બાર"</string>
- <!-- no translation found for nav_bar_layout (3664072994198772020) -->
- <skip />
- <!-- no translation found for nav_bar_left (731491280511316123) -->
- <skip />
- <!-- no translation found for nav_bar_right (2523774879720231974) -->
- <skip />
- <!-- no translation found for nav_bar_button_type (6947806619897153791) -->
- <skip />
- <!-- no translation found for nav_bar_default (8587114043070993007) -->
- <skip />
- <!-- no translation found for nav_bar_buttons:0 (1545641631806817203) -->
- <!-- no translation found for nav_bar_buttons:1 (5742013440802239414) -->
- <!-- no translation found for nav_bar_buttons:2 (8748101184830239843) -->
- <!-- no translation found for nav_bar_buttons:3 (8175437057325747277) -->
- <!-- no translation found for nav_bar_layouts:0 (4967898371682516967) -->
- <!-- no translation found for nav_bar_layouts:1 (6210279084134579668) -->
- <!-- no translation found for nav_bar_layouts:2 (89143234390889289) -->
- <!-- no translation found for nav_bar_layouts:3 (7715533883382410603) -->
+ <string name="nav_bar_layout" msgid="3664072994198772020">"લેઆઉટ"</string>
+ <string name="nav_bar_left" msgid="731491280511316123">"ડાબે"</string>
+ <string name="nav_bar_right" msgid="2523774879720231974">"જમણે"</string>
+ <string name="nav_bar_button_type" msgid="6947806619897153791">"બટનનો પ્રકાર"</string>
+ <string name="nav_bar_default" msgid="8587114043070993007">"(ડિફૉલ્ટ)"</string>
+ <string-array name="nav_bar_buttons">
+ <item msgid="1545641631806817203">"ક્લિપબોર્ડ"</item>
+ <item msgid="5742013440802239414">"કીકોડ"</item>
+ <item msgid="8748101184830239843">"મેનૂ / કીબોર્ડ સ્વિચર"</item>
+ <item msgid="8175437057325747277">"કોઈ નહીં"</item>
+ </string-array>
+ <string-array name="nav_bar_layouts">
+ <item msgid="4967898371682516967">"વિભાજીત (ડિફૉલ્ટ)"</item>
+ <item msgid="6210279084134579668">"કેન્દ્રિત"</item>
+ <item msgid="89143234390889289">"ડાબે-સંરેખિત"</item>
+ <item msgid="7715533883382410603">"જમણે-સંરેખિત"</item>
+ </string-array>
<string name="menu_ime" msgid="4943221416525250684">"મેનૂ / કીબોર્ડ સ્વિચર"</string>
<string name="save" msgid="2311877285724540644">"સાચવો"</string>
<string name="reset" msgid="2448168080964209908">"ફરીથી સેટ કરો"</string>
@@ -630,8 +620,7 @@
<string name="clipboard" msgid="1313879395099896312">"ક્લિપબોર્ડ"</string>
<string name="accessibility_key" msgid="5701989859305675896">"કસ્ટમ નેવિગેશન બટન"</string>
<string name="keycode" msgid="7335281375728356499">"કીકોડ"</string>
- <!-- no translation found for icon (8732339849035837289) -->
- <skip />
+ <string name="icon" msgid="8732339849035837289">"આઇકન"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"ટાઇલ્સ ઉમેરવા માટે ખેંચો"</string>
<string name="drag_to_remove_tiles" msgid="3361212377437088062">"દૂર કરવા માટે અહીં ખેંચો"</string>
<string name="qs_edit" msgid="2232596095725105230">"સંપાદિત કરો"</string>
@@ -682,28 +671,18 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> માંથી <xliff:g id="ID_1">%1$d</xliff:g> પૃષ્ઠ"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"વિસ્તૃત કરો"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"નાનું કરો"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"છોડી દો"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"ફોન ગરમ થઈ રહ્યો છે"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"ફોન ઠંડો થાય ત્યાં સુધી કેટલીક સુવિધાઓ મર્યાદિત હોય છે"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"તમારો ફોન આપમેળે ઠંડો થવાનો પ્રયાસ કરશે. તમે હજી પણ તમારા ફોનનો ઉપયોગ કરી શકો છો, પરંતુ તે કદાચ થોડો ધીમો ચાલે.\n\nતમારો ફોન ઠંડો થઈ જવા પર, તે સામાન્ય રીતે ચાલશે."</string>
- <!-- no translation found for lockscreen_left (6806490081187499505) -->
- <skip />
- <!-- no translation found for lockscreen_right (6093496261656102989) -->
- <skip />
- <!-- no translation found for lockscreen_customize (1288691376862981950) -->
- <skip />
- <!-- no translation found for lockscreen_shortcut (3734369277470360642) -->
- <skip />
- <!-- no translation found for lockscreen_unlock (4934466194763269051) -->
- <skip />
- <!-- no translation found for notification_channel_alerts (4496839309318519037) -->
- <skip />
- <!-- no translation found for notification_channel_screenshot (6314080179230000938) -->
- <skip />
- <!-- no translation found for notification_channel_security (7345516133431326347) -->
- <skip />
- <!-- no translation found for notification_channel_user_status (1436913581465146650) -->
- <skip />
- <!-- no translation found for notification_channel_storage (3077205683020695313) -->
- <skip />
+ <string name="lockscreen_left" msgid="6806490081187499505">"ડાબે"</string>
+ <string name="lockscreen_right" msgid="6093496261656102989">"જમણે"</string>
+ <string name="lockscreen_customize" msgid="1288691376862981950">"શૉર્ટકટ કસ્ટમાઇઝ કરો"</string>
+ <string name="lockscreen_shortcut" msgid="3734369277470360642">"શૉર્ટકટ"</string>
+ <string name="lockscreen_unlock" msgid="4934466194763269051">"પાસવર્ડ માટેનો સંકેત આપો"</string>
+ <string name="notification_channel_alerts" msgid="4496839309318519037">"ચેતવણીઓ"</string>
+ <string name="notification_channel_screenshot" msgid="6314080179230000938">"સ્ક્રીનશૉટ"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"સામાન્ય સંદેશા"</string>
+ <string name="notification_channel_storage" msgid="3077205683020695313">"સ્ટોરેજ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 7676691..b6cba3c 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -532,7 +532,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 मिनट"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 मिनट"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 घंटा"</string>
- <string name="snooze_option_dont_snooze" msgid="655446566007801922">"यद नहीं दिलाएं"</string>
+ <string name="snooze_option_dont_snooze" msgid="655446566007801922">"याद नहीं दिलाएं"</string>
<string name="snooze_undo" msgid="6074877317002985129">"पहले जैसा करें"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> के लिए याद दिलाया गया"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"बैटरी उपयोग"</string>
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"पेज <xliff:g id="ID_2">%2$d</xliff:g> में से <xliff:g id="ID_1">%1$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"विस्तृत करें"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"छोटा करें"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"खारिज करें"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"फ़ोन गर्म हो रहा है"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"फ़ोन के ठंडा होने के दौरान कुछ सुविधाएं सीमित होती हैं"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"आपका फ़ोन अपने आप ठंडा होने की कोशिश करेगा. आप अभी भी अपने फ़ोन का उपयोग कर सकते हैं, लेकिन हो सकता है कि यह धीमी गति से चले.\n\nठंडा हो जाने पर आपका फ़ोन सामान्य रूप से चलेगा."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"पासवर्ड के लिए संकेत दें"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"सूचनाएं"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"स्क्रीनशॉट"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"सुरक्षा"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"उपयोगकर्ता स्थिति"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"सामान्य संदेश"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"जगह"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 07c725b..85a744d 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -673,7 +673,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Stranica <xliff:g id="ID_1">%1$d</xliff:g> od <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Proširivanje"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimiziraj"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Odbaci"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Telefon se zagrijava"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Neke su značajke ograničene dok se telefon hladi"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefon će se automatski pokušati ohladiti. Možete ga nastaviti koristiti, no mogao bi raditi sporije.\n\nKad se ohladi, radit će normalno."</string>
@@ -684,7 +685,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Upit za zaporku"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Upozorenja"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Snimke zaslona"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Sigurnost"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Status korisnika"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Općenite poruke"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Pohrana"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 029e76b..81f3d5e 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>. oldal, összesen: <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Kibontás"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Kis méret"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Elvetés"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"A telefon melegszik"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Bizonyos funkciók korlátozottan működnek a telefon hűlése közben"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"A telefon automatikusan megpróbál lehűlni. Továbbra is tudja használni a telefont, de elképzelhető, hogy működése lelassul.\n\nAmint a telefon lehűl, újra a szokásos módon működik majd."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Jelszókérés"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Értesítések"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Képernyőképek"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Biztonság"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Felhasználói állapot"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Általános üzenetek"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Tárhely"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 761bee1..e5169f2 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -534,7 +534,7 @@
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ժամ"</string>
<string name="snooze_option_dont_snooze" msgid="655446566007801922">"Չհետաձգել"</string>
<string name="snooze_undo" msgid="6074877317002985129">"ՀԵՏԱՐԿԵԼ"</string>
- <string name="snoozed_for_time" msgid="2390718332980204462">"Հետաձգվել է հետևյալ ժամանակով՝ <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
+ <string name="snoozed_for_time" msgid="2390718332980204462">"Հետաձգվել է <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>ով"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Մարտկոցի օգտագործում"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Մարտկոցի տնտեսումը լիցքավորման ժամանակ հասանելի չէ"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Մարտկոցի տնտեսում"</string>
@@ -608,7 +608,7 @@
<item msgid="8175437057325747277">"Չկան"</item>
</string-array>
<string-array name="nav_bar_layouts">
- <item msgid="4967898371682516967">"Բաժանվածծ (կանխադրված)"</item>
+ <item msgid="4967898371682516967">"Բաժանված (կանխադրված)"</item>
<item msgid="6210279084134579668">"Կենտրոնում"</item>
<item msgid="89143234390889289">"Հավասարեցված ձախ"</item>
<item msgid="7715533883382410603">"Հավասարեցված աջ"</item>
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Էջ <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Ընդարձակել"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Ծալել"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Փակել"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Հեռախոսը տաքանում է"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Հովանալու ընթացքում հեռախոսի որոշ գործառույթներ սահմանափակ են"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Ձեր հեռախոսն ավտոմատ կերպով կփորձի hովանալ: Կարող եք շարունակել օգտագործել հեռախոսը, սակայն հնարավոր է, որ այն ավելի դանդաղ աշխատի:\n\nՀովանալուց հետո հեռախոսը կաշխատի կանոնավոր կերպով:"</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Պահանջել գաղտնաբառ"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Ծանուցումներ"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Էկրանի պատկերներ"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Անվտանգություն"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Օգտվողի կարգավիճակը"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Ընդհանուր հաղորդագրություններ"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Հիշողություն"</string>
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 24a7b538..a2d38e9 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Halaman <xliff:g id="ID_1">%1$d</xliff:g> dari <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Luaskan"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimalkan"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Tutup"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Ponsel menjadi hangat"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Beberapa fitur dibatasi saat ponsel mendingin"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Ponsel akan otomatis mencoba mendingin. Anda tetap dapat menggunakan ponsel, tetapi mungkin berjalan lebih lambat.\n\nSetelah dingin, ponsel akan berjalan seperti biasa."</string>
@@ -680,9 +681,8 @@
<string name="lockscreen_customize" msgid="1288691376862981950">"Sesuaikan pintasan"</string>
<string name="lockscreen_shortcut" msgid="3734369277470360642">"Pintasan"</string>
<string name="lockscreen_unlock" msgid="4934466194763269051">"Minta sandi"</string>
- <string name="notification_channel_alerts" msgid="4496839309318519037">"Lansiran"</string>
+ <string name="notification_channel_alerts" msgid="4496839309318519037">"Notifikasi"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshot"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Keamanan"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Status pengguna"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Pesan Umum"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Penyimpanan"</string>
</resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 5f46b92..b0dacfc 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Blaðsíða <xliff:g id="ID_1">%1$d</xliff:g> af <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Stækka"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minnka"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Hunsa"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Síminn er að hitna"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Sumir eiginleikar eru takmarkaðir þegar síminn kælir sig"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Síminn reynir sjálfkrafa að kæla sig. Þú getur enn notað símann en hann gæti verið hægvirkari.\n\nEftir að síminn hefur kælt sig niður virkar hann eðlilega."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Beiðni um aðgangsorð"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Tilkynningar"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Skjámyndir"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Öryggi"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Staða notanda"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Almenn skilaboð"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Geymslurými"</string>
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 2441b7f..8dacab2 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -673,7 +673,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Pagina <xliff:g id="ID_1">%1$d</xliff:g> di <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Espandi"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Riduci a icona"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Ignora"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Il telefono si sta scaldando"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Alcune funzioni limitate durante il raffreddamento del telefono"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Il telefono cercherà automaticamente di raffreddarsi. Puoi comunque usarlo, ma potrebbe essere più lento.\n\nUna volta raffreddato, il telefono funzionerà normalmente."</string>
@@ -684,7 +685,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Richiedi password"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Avvisi"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshot"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Sicurezza"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Stato utente"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Messaggi generali"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Spazio di archiviazione"</string>
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 280b9aa..d39a07a 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -675,7 +675,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"דף <xliff:g id="ID_1">%1$d</xliff:g> מתוך <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"הרחב"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"מזער"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"סגור"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"הטלפון מתחמם"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"חלק מהתכונות מוגבלות כל עוד הטלפון מתקרר"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"קירור הטלפון ייעשה באופן אוטומטי. תוכל עדיין להשתמש בטלפון, אבל ייתכן שהוא יפעל לאט יותר.\n\nהטלפון יחזור לפעול כרגיל לאחר שיתקרר."</string>
@@ -686,7 +687,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"בקש סיסמה"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"התראות"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"צילומי מסך"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"אבטחה"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"סטטוס המשתמש"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"הודעות כלליות"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"אחסון"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 015545e..9ea02b9 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -673,7 +673,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"ページ <xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"展開"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"最小化"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"閉じる"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"スマートフォンの温度が上昇中"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"スマートフォンのクールダウン中は一部の機能が制限されます"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"スマートフォンは自動的にクールダウンを行います。その間もスマートフォンを使用できますが、動作が遅くなる可能性があります。\n\nクールダウンが完了すると、通常どおり動作します。"</string>
@@ -684,7 +685,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"パスワードの入力"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"通知"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"スクリーンショット"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"セキュリティ"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"ユーザー ステータス"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"一般メッセージ"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"ストレージ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index c75d83d..30b503e 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"გვერდი <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>-დან"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"გაშლა"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"ჩაკეცვა"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"დახურვა"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"ტელეფონი ცხელდება"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"ზოგიერთი ფუნქცია შეზღუდული იქნება, სანამ ტელეფონი გაგრილდება"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"თქვენი ტელეფონი გაგრილებას ავტომატურად შეეცდება. შეგიძლიათ გააგრძელოთ მისით სარგებლობა, თუმცა ტელეფონმა შეიძლება უფრო ნელა იმუშაოს.\n\nგაგრილების შემდგომ ის ჩვეულებრივად იმუშავებს."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"პაროლის მოთხოვნა"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"გაფრთხილებები"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"ეკრანის ანაბეჭდები"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"უსაფრთხოება"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"მომხმარებლის სტატუსი"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"ზოგადი შეტყობინებები"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"მეხსიერება"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index d86fcf9..cfcd2ec 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> ішінен <xliff:g id="ID_1">%1$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Жаю"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Кішірейту"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Қабылдамау"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Телефон қызуда"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Телефон толық суығанға дейін, кейбір функциялардың жұмысы шектеледі"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Телефон автоматты түрде суи бастайды. Оны пайдалана бере аласыз, бірақ ол баяуырақ жұмыс істеуі мүмкін.\n\nТелефон суығаннан кейін, оның жұмысы қалпына келеді."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Құпия сөзді сұрау"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Дабылдар"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Скриншоттар"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Қауіпсіздік"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Пайдаланушы күйі"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Жалпы хабарлар"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Жад"</string>
</resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index cfbba6e..a958258 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -602,16 +602,16 @@
<string name="nav_bar_button_type" msgid="6947806619897153791">"ប្រភេទប៊ូតុង"</string>
<string name="nav_bar_default" msgid="8587114043070993007">"(លំនាំដើម)"</string>
<string-array name="nav_bar_buttons">
- <item msgid="1545641631806817203">"ក្ដារតម្បៀតខ្ទាស់"</item>
+ <item msgid="1545641631806817203">"អង្គចងចាំ"</item>
<item msgid="5742013440802239414">"លេខកូដគ្រាប់ចុច"</item>
- <item msgid="8748101184830239843">"កម្មវិធីប្តូរក្តារចុច / ម៉ឺនុយ"</item>
+ <item msgid="8748101184830239843">"ម៉ឺនុយ / កម្មវិធីប្តូរក្តារចុច"</item>
<item msgid="8175437057325747277">"គ្មាន"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="4967898371682516967">"បំបែក (លំនាំដើម)"</item>
<item msgid="6210279084134579668">"ដាក់នៅកណ្តាល"</item>
- <item msgid="89143234390889289">"តម្រឹមខាងឆ្វេង"</item>
- <item msgid="7715533883382410603">"តម្រឹមខាងស្ដាំ"</item>
+ <item msgid="89143234390889289">"តម្រឹមឆ្វេង"</item>
+ <item msgid="7715533883382410603">"តម្រឹមស្ដាំ"</item>
</string-array>
<string name="menu_ime" msgid="4943221416525250684">"កម្មវិធីប្តូរក្តារចុច / ម៉ឺនុយ"</string>
<string name="save" msgid="2311877285724540644">"រក្សាទុក"</string>
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"ទំព័រ <xliff:g id="ID_1">%1$d</xliff:g> នៃ <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"ពង្រីក"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"បង្រួម"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"បដិសេធ"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"ទូរសព្ទនេះកំពុងកើនកម្តៅ"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"មុខងារមួយចំនួននឹងមិនអាចប្រើបានពេញលេញនោះទេ ខណៈពេលដែលទូរសព្ទកំពុងបញ្ចុះកម្តៅ"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"ទូរសព្ទរបស់អ្នកនឹងព្យាយាមបញ្ចុះកម្តៅដោយស្វ័យប្រវត្តិ។ អ្នកនៅតែអាចប្រើទូរសព្ទរបស់អ្នកបានដដែល ប៉ុន្តែវានឹងដំណើរការយឺតជាងមុន។\n\nបន្ទាប់ពីទូរសព្ទរបស់អ្នកត្រជាក់ជាងមុនហើយ វានឹងដំណើរការដូចធម្មតា។"</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"ជំរុញឲ្យបញ្ចូលពាក្យសម្ងាត់"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"ការជូនដំណឹង"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"រូបថតអេក្រង់"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"សុវត្ថិភាព"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"ស្ថានភាពអ្នកប្រើ"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"សារទូទៅ"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"ទំហំផ្ទុក"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 70a8809..ba681db 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -526,24 +526,15 @@
<string name="notification_importance_high" msgid="3316555356062640222">"ಪರದೆಯ ಮೇಲೆ ಧ್ವನಿಮಾಡಿ ಮತ್ತು ಪಾಪ್ ಮಾಡಿ"</string>
<string name="notification_more_settings" msgid="816306283396553571">"ಹೆಚ್ಚಿನ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="notification_done" msgid="5279426047273930175">"ಮುಗಿದಿದೆ"</string>
- <!-- no translation found for notification_menu_accessibility (2046162834248888553) -->
- <skip />
- <!-- no translation found for notification_menu_gear_description (2204480013726775108) -->
- <skip />
- <!-- no translation found for notification_menu_snooze_description (3653669438131034525) -->
- <skip />
- <!-- no translation found for snooze_option_15_min (1068727451405610715) -->
- <skip />
- <!-- no translation found for snooze_option_30_min (867081342535195788) -->
- <skip />
- <!-- no translation found for snooze_option_1_hour (1098086401880077154) -->
- <skip />
- <!-- no translation found for snooze_option_dont_snooze (655446566007801922) -->
- <skip />
- <!-- no translation found for snooze_undo (6074877317002985129) -->
- <skip />
- <!-- no translation found for snoozed_for_time (2390718332980204462) -->
- <skip />
+ <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
+ <string name="notification_menu_gear_description" msgid="2204480013726775108">"ಅಧಿಸೂಚನೆ ನಿಯಂತ್ರಣಗಳು"</string>
+ <string name="notification_menu_snooze_description" msgid="3653669438131034525">"ಅಧಿಸೂಚನೆ ಸ್ನೂಜ್ ಆಯ್ಕೆಗಳು"</string>
+ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 ನಿಮಿಷಗಳು"</string>
+ <string name="snooze_option_30_min" msgid="867081342535195788">"30 ನಿಮಿಷಗಳು"</string>
+ <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ಗಂಟೆ"</string>
+ <string name="snooze_option_dont_snooze" msgid="655446566007801922">"ಸ್ನೂಜ್ ಮಾಡಬೇಡಿ"</string>
+ <string name="snooze_undo" msgid="6074877317002985129">"ರದ್ದುಮಾಡಿ"</string>
+ <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> ಗೆ ಸ್ನೂಜ್ ಮಾಡಲಾಗಿದೆ"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"ಬ್ಯಾಟರಿ ಬಳಕೆ"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"ಚಾರ್ಜಿಂಗ್ ಸಮಯದಲ್ಲಿ ಬ್ಯಾಟರಿ ಸೇವರ್ ಲಭ್ಯವಿರುವುದಿಲ್ಲ"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"ಬ್ಯಾಟರಿ ಸೇವರ್"</string>
@@ -605,24 +596,23 @@
<string name="switch_bar_on" msgid="1142437840752794229">"ಆನ್"</string>
<string name="switch_bar_off" msgid="8803270596930432874">"ಆಫ್"</string>
<string name="nav_bar" msgid="1993221402773877607">"ನ್ಯಾವಿಗೇಷನ್ ಬಾರ್"</string>
- <!-- no translation found for nav_bar_layout (3664072994198772020) -->
- <skip />
- <!-- no translation found for nav_bar_left (731491280511316123) -->
- <skip />
- <!-- no translation found for nav_bar_right (2523774879720231974) -->
- <skip />
- <!-- no translation found for nav_bar_button_type (6947806619897153791) -->
- <skip />
- <!-- no translation found for nav_bar_default (8587114043070993007) -->
- <skip />
- <!-- no translation found for nav_bar_buttons:0 (1545641631806817203) -->
- <!-- no translation found for nav_bar_buttons:1 (5742013440802239414) -->
- <!-- no translation found for nav_bar_buttons:2 (8748101184830239843) -->
- <!-- no translation found for nav_bar_buttons:3 (8175437057325747277) -->
- <!-- no translation found for nav_bar_layouts:0 (4967898371682516967) -->
- <!-- no translation found for nav_bar_layouts:1 (6210279084134579668) -->
- <!-- no translation found for nav_bar_layouts:2 (89143234390889289) -->
- <!-- no translation found for nav_bar_layouts:3 (7715533883382410603) -->
+ <string name="nav_bar_layout" msgid="3664072994198772020">"ಲೇಔಟ್"</string>
+ <string name="nav_bar_left" msgid="731491280511316123">"ಎಡ"</string>
+ <string name="nav_bar_right" msgid="2523774879720231974">"ಬಲ"</string>
+ <string name="nav_bar_button_type" msgid="6947806619897153791">"ಬಟನ್ ವಿಧ"</string>
+ <string name="nav_bar_default" msgid="8587114043070993007">"(ಡಿಫಾಲ್ಟ್)"</string>
+ <string-array name="nav_bar_buttons">
+ <item msgid="1545641631806817203">"ಕ್ಲಿಪ್ಬೋರ್ಡ್"</item>
+ <item msgid="5742013440802239414">"ಕೀಕೋಡ್"</item>
+ <item msgid="8748101184830239843">"ಮೆನು / ಕೀಬೋರ್ಡ್ ಬದಲಾಯಿಸುವಿಕೆ"</item>
+ <item msgid="8175437057325747277">"ಯಾವುದೂ ಅಲ್ಲ"</item>
+ </string-array>
+ <string-array name="nav_bar_layouts">
+ <item msgid="4967898371682516967">"ವಿಭಜಿಸಲಾಗಿದೆ (ಡಿಫಾಲ್ಟ್)"</item>
+ <item msgid="6210279084134579668">"ಕೇಂದ್ರೀಕೃತ"</item>
+ <item msgid="89143234390889289">"ಎಡಕ್ಕೆ ಹೊಂದಿಸಿರುವುದು"</item>
+ <item msgid="7715533883382410603">"ಬಲಕ್ಕೆ ಹೊಂದಿಸಿರುವುದು"</item>
+ </string-array>
<string name="menu_ime" msgid="4943221416525250684">"ಮೆನು / ಕೀಬೋರ್ಡ್ ಬದಲಾಯಿಸುವಿಕೆ"</string>
<string name="save" msgid="2311877285724540644">"ಉಳಿಸು"</string>
<string name="reset" msgid="2448168080964209908">"ಮರುಹೊಂದಿಸು"</string>
@@ -630,8 +620,7 @@
<string name="clipboard" msgid="1313879395099896312">"ಕ್ಲಿಪ್ಬೋರ್ಡ್"</string>
<string name="accessibility_key" msgid="5701989859305675896">"ಕಸ್ಟಮ್ ನ್ಯಾವಿಗೇಷನ್ ಬಟನ್"</string>
<string name="keycode" msgid="7335281375728356499">"ಕೀಕೋಡ್"</string>
- <!-- no translation found for icon (8732339849035837289) -->
- <skip />
+ <string name="icon" msgid="8732339849035837289">"ಐಕಾನ್"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"ಟೈಲ್ಗಳನ್ನು ಸೇರಿಸಲು ಡ್ರ್ಯಾಗ್ ಮಾಡಿ"</string>
<string name="drag_to_remove_tiles" msgid="3361212377437088062">"ತೆಗೆದುಹಾಕಲು ಇಲ್ಲಿ ಡ್ರ್ಯಾಗ್ ಮಾಡಿ"</string>
<string name="qs_edit" msgid="2232596095725105230">"ಎಡಿಟ್"</string>
@@ -682,28 +671,18 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> ರಲ್ಲಿ <xliff:g id="ID_1">%1$d</xliff:g> ಪುಟ"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"ವಿಸ್ತೃತಗೊಳಿಸು"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"ಕುಗ್ಗಿಸಿ"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"ವಜಾಗೊಳಿಸಿ"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"ಫೋನ್ ಬಿಸಿಯಾಗುತ್ತಿದೆ"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"ಫೋನ್ ತಣ್ಣಗಾಗುವವರೆಗೂ ಕೆಲವು ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಸೀಮಿತಗೊಳಿಸುತ್ತದೆ"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"ನಿಮ್ಮ ಫೋನ್ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ತಣ್ಣಗಾಗಲು ಪ್ರಯತ್ನಿಸುತ್ತದೆ. ನಿಮ್ಮ ಫೋನ್ ಅನ್ನು ನೀವು ಈಗಲೂ ಬಳಸಬಹುದಾಗಿರುತ್ತದೆ, ಆದರೆ ಇದು ನಿಧಾನವಾಗಿರಬಹುದು.\n\nಒಮ್ಮೆ ನಿಮ್ಮ ಫೋನ್ ತಣ್ಣಗಾದ ನಂತರ ಇದು ಸಾಮಾನ್ಯ ರೀತಿಯಲ್ಲಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ."</string>
- <!-- no translation found for lockscreen_left (6806490081187499505) -->
- <skip />
- <!-- no translation found for lockscreen_right (6093496261656102989) -->
- <skip />
- <!-- no translation found for lockscreen_customize (1288691376862981950) -->
- <skip />
- <!-- no translation found for lockscreen_shortcut (3734369277470360642) -->
- <skip />
- <!-- no translation found for lockscreen_unlock (4934466194763269051) -->
- <skip />
- <!-- no translation found for notification_channel_alerts (4496839309318519037) -->
- <skip />
- <!-- no translation found for notification_channel_screenshot (6314080179230000938) -->
- <skip />
- <!-- no translation found for notification_channel_security (7345516133431326347) -->
- <skip />
- <!-- no translation found for notification_channel_user_status (1436913581465146650) -->
- <skip />
- <!-- no translation found for notification_channel_storage (3077205683020695313) -->
- <skip />
+ <string name="lockscreen_left" msgid="6806490081187499505">"ಎಡ"</string>
+ <string name="lockscreen_right" msgid="6093496261656102989">"ಬಲ"</string>
+ <string name="lockscreen_customize" msgid="1288691376862981950">"ಶಾರ್ಟ್ಕಟ್ ಕಸ್ಟಮೈಸ್ ಮಾಡಿ"</string>
+ <string name="lockscreen_shortcut" msgid="3734369277470360642">"ಶಾರ್ಟ್ಕಟ್"</string>
+ <string name="lockscreen_unlock" msgid="4934466194763269051">"ಪಾಸ್ವರ್ಡ್ ಕೇಳಿ"</string>
+ <string name="notification_channel_alerts" msgid="4496839309318519037">"ಎಚ್ಚರಿಕೆಗಳು"</string>
+ <string name="notification_channel_screenshot" msgid="6314080179230000938">"ಸ್ಕ್ರೀನ್ಶಾಟ್ಗಳು"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"ಸಾಮಾನ್ಯ ಸಂದೇಶಗಳು"</string>
+ <string name="notification_channel_storage" msgid="3077205683020695313">"ಸಂಗ್ರಹಣೆ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 4b59ad2..c5faa18 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -673,7 +673,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g>페이지 중 <xliff:g id="ID_1">%1$d</xliff:g>페이지"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"펼치기"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"최소화"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"닫기"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"휴대전화 온도가 높음"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"휴대전화 온도를 낮추는 동안 일부 기능이 제한됩니다."</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"휴대전화 온도를 자동으로 낮추려고 시도합니다. 휴대전화를 계속 사용할 수는 있지만 작동이 느려질 수도 있습니다.\n\n휴대전화 온도가 낮아지면 정상적으로 작동됩니다."</string>
@@ -684,7 +685,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"비밀번호 요청"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"알림"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"스크린샷"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"보안"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"사용자 상태"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"일반 메시지"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"저장소"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 53b1098..6f57a73 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -620,7 +620,7 @@
<string name="clipboard" msgid="1313879395099896312">"Алмашуу буфери"</string>
<string name="accessibility_key" msgid="5701989859305675896">"Ыңгайлаштырылган чабыттоо баскычы"</string>
<string name="keycode" msgid="7335281375728356499">"Баскыч коду"</string>
- <string name="icon" msgid="8732339849035837289">"Сөлөкөт"</string>
+ <string name="icon" msgid="8732339849035837289">"Сүрөтчө"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Керектүү нерселерди сүйрөп кошуңуз"</string>
<string name="drag_to_remove_tiles" msgid="3361212377437088062">"Алып салуу үчүн бул жерге сүйрөңүз"</string>
<string name="qs_edit" msgid="2232596095725105230">"Түзөтүү"</string>
@@ -671,18 +671,18 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> ичинен <xliff:g id="ID_1">%1$d</xliff:g>-бет"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Жайып көрсөтүү"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Кичирейтүү"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Этибарга албоо"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Телефонуңуз ысып баратат"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Телефон сууганча айрым элементтердин иши чектелген"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Телефонуңуз автоматтык түрдө сууйт. Аны колдоно берсеңиз болот, бирок ал жайыраак иштеп калат.\n\nТелефонуңуз суугандан кийин адаттагыдай эле иштеп баштайт."</string>
<string name="lockscreen_left" msgid="6806490081187499505">"Сол жакта"</string>
<string name="lockscreen_right" msgid="6093496261656102989">"Оң жакта"</string>
- <string name="lockscreen_customize" msgid="1288691376862981950">"Кыска жолду ыңгайлаштыруу"</string>
+ <string name="lockscreen_customize" msgid="1288691376862981950">"Кыска жолду тууралоо"</string>
<string name="lockscreen_shortcut" msgid="3734369277470360642">"Кыска жол"</string>
- <string name="lockscreen_unlock" msgid="4934466194763269051">"Сырсөз үчүн ишарат"</string>
- <string name="notification_channel_alerts" msgid="4496839309318519037">"Айгай кабарлар"</string>
+ <string name="lockscreen_unlock" msgid="4934466194763269051">"Сырсөздү суроо"</string>
+ <string name="notification_channel_alerts" msgid="4496839309318519037">"Эскертүүлөр"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Скриншоттор"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Коопсуздук"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Колдонуучунун абалы"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Жалпы билдирүүлөр"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Сактагыч"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index aea7812..c7475bc 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g> ຈາກທັງໝົດ <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"ຂະຫຍາຍ"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"ຫຍໍ້"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"ປິດໄວ້"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"ໂທລະສັບກຳລັງຮ້ອນຂຶ້ນ"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"ຄຸນສົມບັດບາງຢ່າງຖືກຈຳກັດໄວ້ເນື່ອງໃນເວລາຫຼຸດອຸນຫະພູມຂອງໂທລະສັບ"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"ໂທລະສັບຂອງທ່ານຈະພະຍາຍາມລົດອຸນຫະພູມລົງ. ທ່ານຍັງຄົງສາມາດໃຊ້ໂທລະສັບຂອງທ່ານໄດ້ຢູ່, ແຕ່ມັນຈະເຮັດວຽກຊ້າລົງ.\n\nເມື່ອໂທລະສັບຂອງທ່ານບໍ່ຮ້ອນຫຼາຍແລ້ວ, ມັນຈະກັບມາເຮັດວຽກຕາມປົກກະຕິ."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"ຖາມຫາລະຫັດຜ່ານ"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"ການເຕືອນ"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"ຮູບຖ່າຍໜ້າຈໍ"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"ຄວາມປອດໄພ"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"ສະຖານະຜູ້ໃຊ້"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"ຂໍ້ຄວາມທົ່ວໄປ"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"ບ່ອນເກັບຂໍ້ມູນ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 83f4d15..e6713f2 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -675,7 +675,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g> psl. iš <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Išskleisti"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Sumažinti"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Atsisakyti"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Telefonas kaista"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Kai kurios funkcijos gali neveikti, kol telefonas vėsta"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefonas automatiškai bandys atvėsti. Telefoną vis tiek galėsite naudoti, tačiau jis gali veikti lėčiau.\n\nKai telefonas atvės, jis veiks įprastai."</string>
@@ -686,7 +687,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Paraginti įvesti slaptažodį"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Įspėjimai"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Ekrano kopijos"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Sauga"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Naudotojų būsena"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Bendrieji pranešimai"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Saugykla"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 09581e8..ba6ce3c 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -673,7 +673,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>. lpp. no <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Izvērst"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizēt"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Noraidīt"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Tālrunis kļūst silts"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Dažas funkcijas ir ierobežotas, kamēr tālrunis mēģina atdzist"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Jūsu tālrunis automātiski mēģinās atdzist. Jūs joprojām varat izmantot tālruni, taču tas, iespējams, darbosies lēnāk.\n\nTiklīdz tālrunis būs atdzisis, tas darbosies normāli."</string>
@@ -684,7 +685,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Pieprasīt paroli"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Brīdinājumi"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Ekrānuzņēmumi"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Drošība"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Lietotāju statuss"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Vispārīgi ziņojumi"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Krātuve"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 6db8e58..5308d65 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Страница <xliff:g id="ID_1">%1$d</xliff:g> од <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Проширете"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Минимизирај"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Отфрли"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Телефонот се загрева"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Некои функции се ограничени додека телефонот се лади"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Телефонот автоматски ќе се обиде да се олади. Вие сепак ќе може да го користите, но тој може да работи побавно.\n\nОткако ќе се олади, ќе работи нормално."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Побарај лозинка"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Предупредувања"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Слики од екранот"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Безбедност"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Кориснички статус"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Општи пораки"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Меморија"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 0cdd351..cf32631 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -526,24 +526,15 @@
<string name="notification_importance_high" msgid="3316555356062640222">"ശബ്ദമുണ്ടാക്കുക, സ്ക്രീനിൽ കാണിക്കുക"</string>
<string name="notification_more_settings" msgid="816306283396553571">"കൂടുതൽ ക്രമീകരണം"</string>
<string name="notification_done" msgid="5279426047273930175">"പൂർത്തിയായി"</string>
- <!-- no translation found for notification_menu_accessibility (2046162834248888553) -->
- <skip />
- <!-- no translation found for notification_menu_gear_description (2204480013726775108) -->
- <skip />
- <!-- no translation found for notification_menu_snooze_description (3653669438131034525) -->
- <skip />
- <!-- no translation found for snooze_option_15_min (1068727451405610715) -->
- <skip />
- <!-- no translation found for snooze_option_30_min (867081342535195788) -->
- <skip />
- <!-- no translation found for snooze_option_1_hour (1098086401880077154) -->
- <skip />
- <!-- no translation found for snooze_option_dont_snooze (655446566007801922) -->
- <skip />
- <!-- no translation found for snooze_undo (6074877317002985129) -->
- <skip />
- <!-- no translation found for snoozed_for_time (2390718332980204462) -->
- <skip />
+ <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
+ <string name="notification_menu_gear_description" msgid="2204480013726775108">"അറിയിപ്പ് നിയന്ത്രണങ്ങൾ"</string>
+ <string name="notification_menu_snooze_description" msgid="3653669438131034525">"അറിയിപ്പ് സ്നൂസ് ഓപ്ഷനുകൾ"</string>
+ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 മിനിറ്റ്"</string>
+ <string name="snooze_option_30_min" msgid="867081342535195788">"30 മിനിറ്റ്"</string>
+ <string name="snooze_option_1_hour" msgid="1098086401880077154">"ഒരു മണിക്കൂർ"</string>
+ <string name="snooze_option_dont_snooze" msgid="655446566007801922">"സ്നൂസ് ചെയ്യരുത്"</string>
+ <string name="snooze_undo" msgid="6074877317002985129">"പഴയപടിയാക്കുക"</string>
+ <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> സമയത്തേക്ക് സ്നൂസ് ചെയ്തു"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"ബാറ്ററി ഉപയോഗം"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"ചാർജുചെയ്യുന്ന സമയത്ത് ബാറ്ററി സേവർ ലഭ്യമല്ല"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"ബാറ്ററി സേവർ"</string>
@@ -605,24 +596,23 @@
<string name="switch_bar_on" msgid="1142437840752794229">"ഓൺ"</string>
<string name="switch_bar_off" msgid="8803270596930432874">"ഓഫ്"</string>
<string name="nav_bar" msgid="1993221402773877607">"നാവിഗേഷൻ ബാർ"</string>
- <!-- no translation found for nav_bar_layout (3664072994198772020) -->
- <skip />
- <!-- no translation found for nav_bar_left (731491280511316123) -->
- <skip />
- <!-- no translation found for nav_bar_right (2523774879720231974) -->
- <skip />
- <!-- no translation found for nav_bar_button_type (6947806619897153791) -->
- <skip />
- <!-- no translation found for nav_bar_default (8587114043070993007) -->
- <skip />
- <!-- no translation found for nav_bar_buttons:0 (1545641631806817203) -->
- <!-- no translation found for nav_bar_buttons:1 (5742013440802239414) -->
- <!-- no translation found for nav_bar_buttons:2 (8748101184830239843) -->
- <!-- no translation found for nav_bar_buttons:3 (8175437057325747277) -->
- <!-- no translation found for nav_bar_layouts:0 (4967898371682516967) -->
- <!-- no translation found for nav_bar_layouts:1 (6210279084134579668) -->
- <!-- no translation found for nav_bar_layouts:2 (89143234390889289) -->
- <!-- no translation found for nav_bar_layouts:3 (7715533883382410603) -->
+ <string name="nav_bar_layout" msgid="3664072994198772020">"ലേഔട്ട്"</string>
+ <string name="nav_bar_left" msgid="731491280511316123">"ഇടത്"</string>
+ <string name="nav_bar_right" msgid="2523774879720231974">"വലത്"</string>
+ <string name="nav_bar_button_type" msgid="6947806619897153791">"ബട്ടൺ തരം"</string>
+ <string name="nav_bar_default" msgid="8587114043070993007">"(ഡിഫോൾട്ട്)"</string>
+ <string-array name="nav_bar_buttons">
+ <item msgid="1545641631806817203">"ക്ലിപ്പ്ബോർഡ്"</item>
+ <item msgid="5742013440802239414">"കീകോഡ്"</item>
+ <item msgid="8748101184830239843">"മെനു / കീബോർഡ് സ്വിച്ചർ"</item>
+ <item msgid="8175437057325747277">"ഒന്നുമില്ല"</item>
+ </string-array>
+ <string-array name="nav_bar_layouts">
+ <item msgid="4967898371682516967">"വിഭജിച്ചത് (ഡിഫോൾട്ട്)"</item>
+ <item msgid="6210279084134579668">"മധ്യഭാഗത്ത് വിന്യസിച്ചത്"</item>
+ <item msgid="89143234390889289">"ഇടതുവശത്ത് വിന്യസിച്ചത്"</item>
+ <item msgid="7715533883382410603">"വലതുവശത്ത് വിന്യസിച്ചത്"</item>
+ </string-array>
<string name="menu_ime" msgid="4943221416525250684">"മെനു / കീബോർഡ് സ്വിച്ചർ"</string>
<string name="save" msgid="2311877285724540644">"സംരക്ഷിക്കുക"</string>
<string name="reset" msgid="2448168080964209908">"പുനഃസജ്ജമാക്കുക"</string>
@@ -630,8 +620,7 @@
<string name="clipboard" msgid="1313879395099896312">"ക്ലിപ്പ്ബോർഡ്"</string>
<string name="accessibility_key" msgid="5701989859305675896">"ഇഷ്ടാനുസൃത നാവിഗേഷൻ ബട്ടൺ"</string>
<string name="keycode" msgid="7335281375728356499">"കീകോഡ്"</string>
- <!-- no translation found for icon (8732339849035837289) -->
- <skip />
+ <string name="icon" msgid="8732339849035837289">"ഐക്കൺ"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"ടൈലുകൾ ചേർക്കുന്നതിന് വലിച്ചിടുക"</string>
<string name="drag_to_remove_tiles" msgid="3361212377437088062">"നീക്കംചെയ്യുന്നതിന് ഇവിടെ വലിച്ചിടുക"</string>
<string name="qs_edit" msgid="2232596095725105230">"എഡിറ്റുചെയ്യുക"</string>
@@ -682,28 +671,19 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"പേജ് <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"വികസിപ്പിക്കുക"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"ചെറുതാക്കുക"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"നിരസിക്കുക"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"ഫോൺ ചൂടായിക്കൊണ്ടിരിക്കുന്നു"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"ഫോൺ തണുത്തുകൊണ്ടിരിക്കുമ്പോൾ ചില ഫീച്ചറുകൾ പരിമിതപ്പെടുത്തപ്പെടും"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"നിങ്ങളുടെ ഫോൺ സ്വയമേവ തണുക്കാൻ ശ്രമിക്കും. നിങ്ങൾക്ക് അപ്പോഴും ഫോൺ ഉപയോഗിക്കാമെങ്കിലും പ്രവർത്തനം മന്ദഗതിയിലായിരിക്കും.\n\nതണുത്തുകഴിഞ്ഞാൽ, ഫോൺ സാധാരണ ഗതിയിൽ പ്രവർത്തിക്കും."</string>
- <!-- no translation found for lockscreen_left (6806490081187499505) -->
+ <string name="lockscreen_left" msgid="6806490081187499505">"ഇടത്"</string>
+ <string name="lockscreen_right" msgid="6093496261656102989">"വലത്"</string>
+ <string name="lockscreen_customize" msgid="1288691376862981950">"കുറുക്കുവഴി ഇഷ്ടാനുസൃതമാക്കുക"</string>
+ <string name="lockscreen_shortcut" msgid="3734369277470360642">"കുറുക്കുവഴി"</string>
+ <string name="lockscreen_unlock" msgid="4934466194763269051">"പാസ്വേഡ് ആവശ്യപ്പെടുക"</string>
+ <string name="notification_channel_alerts" msgid="4496839309318519037">"അലേർട്ടുകൾ"</string>
+ <string name="notification_channel_screenshot" msgid="6314080179230000938">"സ്ക്രീൻഷോട്ടുകൾ"</string>
+ <!-- no translation found for notification_channel_general (4525309436693914482) -->
<skip />
- <!-- no translation found for lockscreen_right (6093496261656102989) -->
- <skip />
- <!-- no translation found for lockscreen_customize (1288691376862981950) -->
- <skip />
- <!-- no translation found for lockscreen_shortcut (3734369277470360642) -->
- <skip />
- <!-- no translation found for lockscreen_unlock (4934466194763269051) -->
- <skip />
- <!-- no translation found for notification_channel_alerts (4496839309318519037) -->
- <skip />
- <!-- no translation found for notification_channel_screenshot (6314080179230000938) -->
- <skip />
- <!-- no translation found for notification_channel_security (7345516133431326347) -->
- <skip />
- <!-- no translation found for notification_channel_user_status (1436913581465146650) -->
- <skip />
- <!-- no translation found for notification_channel_storage (3077205683020695313) -->
- <skip />
+ <string name="notification_channel_storage" msgid="3077205683020695313">"സ്റ്റോറേജ്"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index d184f84..336429f 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g>-н <xliff:g id="ID_1">%1$d</xliff:g>-р хуудас"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Дэлгэх"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Багасгах"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Хаах"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Утас халж эхэлж байна"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Таны утас хөрж байх зуур зарим онцлогийг хязгаарласан"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Таны утас автоматаар хөрөх болно. Та утсаа ашиглаж болох хэдий ч удаан ажиллаж болзошгүй.\n\nТаны утас хөрсний дараагаар хэвийн ажиллана."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Нууц үг шаардах"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Сануулга"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Дэлгэцийн зураг дарах"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Аюулгүй байдал"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Хэрэглэгчийн төлөв"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Энгийн зурвас"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Хадгалах сан"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index f26f1e52..7b09c9d 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -526,24 +526,15 @@
<string name="notification_importance_high" msgid="3316555356062640222">"ध्वनी करा आणि स्क्रीनवर पॉप करा"</string>
<string name="notification_more_settings" msgid="816306283396553571">"अधिक सेटिंग्ज"</string>
<string name="notification_done" msgid="5279426047273930175">"पूर्ण झाले"</string>
- <!-- no translation found for notification_menu_accessibility (2046162834248888553) -->
- <skip />
- <!-- no translation found for notification_menu_gear_description (2204480013726775108) -->
- <skip />
- <!-- no translation found for notification_menu_snooze_description (3653669438131034525) -->
- <skip />
- <!-- no translation found for snooze_option_15_min (1068727451405610715) -->
- <skip />
- <!-- no translation found for snooze_option_30_min (867081342535195788) -->
- <skip />
- <!-- no translation found for snooze_option_1_hour (1098086401880077154) -->
- <skip />
- <!-- no translation found for snooze_option_dont_snooze (655446566007801922) -->
- <skip />
- <!-- no translation found for snooze_undo (6074877317002985129) -->
- <skip />
- <!-- no translation found for snoozed_for_time (2390718332980204462) -->
- <skip />
+ <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
+ <string name="notification_menu_gear_description" msgid="2204480013726775108">"सूचना नियंत्रणे"</string>
+ <string name="notification_menu_snooze_description" msgid="3653669438131034525">"सूचना स्नूझ पर्याय"</string>
+ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 मिनिटे"</string>
+ <string name="snooze_option_30_min" msgid="867081342535195788">"30 मिनिटे"</string>
+ <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 तास"</string>
+ <string name="snooze_option_dont_snooze" msgid="655446566007801922">"स्नूझ करू नका"</string>
+ <string name="snooze_undo" msgid="6074877317002985129">"पूर्ववत करा"</string>
+ <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> साठी स्नूझ करा"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"बॅटरी वापर"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"चार्ज करताना बॅटरी बचतकर्ता उपलब्ध नाही"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"बॅटरी बचतकर्ता"</string>
@@ -605,24 +596,23 @@
<string name="switch_bar_on" msgid="1142437840752794229">"चालू"</string>
<string name="switch_bar_off" msgid="8803270596930432874">"बंद"</string>
<string name="nav_bar" msgid="1993221402773877607">"नॅव्हिगेशन बार"</string>
- <!-- no translation found for nav_bar_layout (3664072994198772020) -->
- <skip />
- <!-- no translation found for nav_bar_left (731491280511316123) -->
- <skip />
- <!-- no translation found for nav_bar_right (2523774879720231974) -->
- <skip />
- <!-- no translation found for nav_bar_button_type (6947806619897153791) -->
- <skip />
- <!-- no translation found for nav_bar_default (8587114043070993007) -->
- <skip />
- <!-- no translation found for nav_bar_buttons:0 (1545641631806817203) -->
- <!-- no translation found for nav_bar_buttons:1 (5742013440802239414) -->
- <!-- no translation found for nav_bar_buttons:2 (8748101184830239843) -->
- <!-- no translation found for nav_bar_buttons:3 (8175437057325747277) -->
- <!-- no translation found for nav_bar_layouts:0 (4967898371682516967) -->
- <!-- no translation found for nav_bar_layouts:1 (6210279084134579668) -->
- <!-- no translation found for nav_bar_layouts:2 (89143234390889289) -->
- <!-- no translation found for nav_bar_layouts:3 (7715533883382410603) -->
+ <string name="nav_bar_layout" msgid="3664072994198772020">"लेआउट"</string>
+ <string name="nav_bar_left" msgid="731491280511316123">"डावा"</string>
+ <string name="nav_bar_right" msgid="2523774879720231974">"उजवा"</string>
+ <string name="nav_bar_button_type" msgid="6947806619897153791">"बटणाचा प्रकार"</string>
+ <string name="nav_bar_default" msgid="8587114043070993007">"(डीफॉल्ट)"</string>
+ <string-array name="nav_bar_buttons">
+ <item msgid="1545641631806817203">"क्लिपबोर्ड"</item>
+ <item msgid="5742013440802239414">"कीकोड"</item>
+ <item msgid="8748101184830239843">"मेनू / कीबोर्ड स्विचर"</item>
+ <item msgid="8175437057325747277">"काहीही नाही"</item>
+ </string-array>
+ <string-array name="nav_bar_layouts">
+ <item msgid="4967898371682516967">"विभाजित (डीफॉल्ट)"</item>
+ <item msgid="6210279084134579668">"मध्यवर्ती"</item>
+ <item msgid="89143234390889289">"डावे-संरेखित"</item>
+ <item msgid="7715533883382410603">"उजवे-संरेखित"</item>
+ </string-array>
<string name="menu_ime" msgid="4943221416525250684">"मेनू / कीबोर्ड स्विचर"</string>
<string name="save" msgid="2311877285724540644">"जतन करा"</string>
<string name="reset" msgid="2448168080964209908">"रीसेट करा"</string>
@@ -630,8 +620,7 @@
<string name="clipboard" msgid="1313879395099896312">"क्लिपबोर्ड"</string>
<string name="accessibility_key" msgid="5701989859305675896">"सानुकूल नेव्हिगेशन बटण"</string>
<string name="keycode" msgid="7335281375728356499">"कीकोड"</string>
- <!-- no translation found for icon (8732339849035837289) -->
- <skip />
+ <string name="icon" msgid="8732339849035837289">"चिन्ह"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"टाइल जोडण्यासाठी ड्रॅग करा"</string>
<string name="drag_to_remove_tiles" msgid="3361212377437088062">"काढण्यासाठी येथे ड्रॅग करा"</string>
<string name="qs_edit" msgid="2232596095725105230">"संपादित करा"</string>
@@ -682,28 +671,19 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"पृष्ठ <xliff:g id="ID_2">%2$d</xliff:g> पैकी <xliff:g id="ID_1">%1$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"विस्तृत करा"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"लहान करा"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"डिसमिस करा"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"फोन ऊष्ण होत आहे"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"फोन थंड होत असताना काही वैशिष्ट्ये मर्यादित असतात"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"आपला फोन स्वयंचलितपणे थंड होईल. आपण अद्यापही आपला फोन वापरू शकता परंतु तो कदाचित धीमेपणे कार्य करेल.\n\nआपला फोन एकदा थंड झाला की, तो सामान्यपणे कार्य करेल."</string>
- <!-- no translation found for lockscreen_left (6806490081187499505) -->
+ <string name="lockscreen_left" msgid="6806490081187499505">"डावा"</string>
+ <string name="lockscreen_right" msgid="6093496261656102989">"उजवा"</string>
+ <string name="lockscreen_customize" msgid="1288691376862981950">"शॉर्टकट सानुकूल करा"</string>
+ <string name="lockscreen_shortcut" msgid="3734369277470360642">"शॉर्टकट"</string>
+ <string name="lockscreen_unlock" msgid="4934466194763269051">"संकेतशब्दासाठी संकेत"</string>
+ <string name="notification_channel_alerts" msgid="4496839309318519037">"सूचना"</string>
+ <string name="notification_channel_screenshot" msgid="6314080179230000938">"स्क्रीनशॉट"</string>
+ <!-- no translation found for notification_channel_general (4525309436693914482) -->
<skip />
- <!-- no translation found for lockscreen_right (6093496261656102989) -->
- <skip />
- <!-- no translation found for lockscreen_customize (1288691376862981950) -->
- <skip />
- <!-- no translation found for lockscreen_shortcut (3734369277470360642) -->
- <skip />
- <!-- no translation found for lockscreen_unlock (4934466194763269051) -->
- <skip />
- <!-- no translation found for notification_channel_alerts (4496839309318519037) -->
- <skip />
- <!-- no translation found for notification_channel_screenshot (6314080179230000938) -->
- <skip />
- <!-- no translation found for notification_channel_security (7345516133431326347) -->
- <skip />
- <!-- no translation found for notification_channel_user_status (1436913581465146650) -->
- <skip />
- <!-- no translation found for notification_channel_storage (3077205683020695313) -->
- <skip />
+ <string name="notification_channel_storage" msgid="3077205683020695313">"संचय"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 18fa6d0..9ba75b2 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Halaman <xliff:g id="ID_1">%1$d</xliff:g> daripada <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Kembangkan"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimumkan"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Ketepikan"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Telefon semakin panas"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Sesetengah ciri adalah terhad semasa telefon menyejuk"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefon anda akan cuba menyejuk secara automatik. Anda masih dapat menggunakan telefon itu tetapi telefon tersebut mungkin berjalan lebih perlahan.\n\nSetelah telefon anda sejuk, telefon itu akan berjalan seperti biasa."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Gesa untuk kata laluan"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Makluman"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Tangkapan skrin"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Keselamatan"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Status pengguna"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Mesej Am"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Storan"</string>
</resources>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 1c4a83e..32ff25d 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"စာမျက်နှာ <xliff:g id="ID_2">%2$d</xliff:g> အနက်မှ စာမျက်နှာ <xliff:g id="ID_1">%1$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"ချဲ့ရန်"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"ချုံ့ရန်"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"ပယ်ရန်"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"ဖုန်း ပူနွေးလာပါပြီ"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"ဖုန်းကို အေးအောင်ပြုလုပ်နေစဉ်တွင် အချို့ဝန်ဆောင်မှုများကို ကန့်သတ်ထားပါသည်"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"သင့်ဖုန်းသည် အလိုအလျောက် ပြန်အေးသွားပါလိမ့်မည်။ ဖုန်းကို အသုံးပြုနိုင်ပါသေးသည် သို့သော် ပိုနှေးနိုင်ပါသည်။\n\nသင့်ဖုန်း အေးသွားသည်နှင့် ပုံမှန်အတိုင်း ပြန်အလုပ်လုပ်ပါလိမ့်မည်။"</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"စကားဝှက်ကို မေးရန်"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"သတိပေးချက်များ"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"မျက်နှာပြင်ဓာတ်ပုံများ"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"လုံခြုံရေး"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"အသုံးပြုသူ အခြေအနေ"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"အထွေထွေ မက်ဆေ့ဂျ်များ"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"သိုလှောင်မှုများ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index d546e92..6624583 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -528,7 +528,7 @@
<string name="notification_done" msgid="5279426047273930175">"Ferdig"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"varselinnstillinger"</string>
- <string name="notification_menu_snooze_description" msgid="3653669438131034525">"utsettelsesalternativer for varsler"</string>
+ <string name="notification_menu_snooze_description" msgid="3653669438131034525">"slumrealternativer for varsler"</string>
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutter"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minutter"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 time"</string>
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Side <xliff:g id="ID_1">%1$d</xliff:g> av <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Vis"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimer"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Avvis"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Telefonen begynner å bli varm"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Enkelte funksjoner er begrenset mens telefonen kjøles ned"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefonen din kommer til å prøve å kjøle seg ned automatisk. Du kan fremdeles bruke telefonen, men den kjører muligens saktere.\n\nTelefonen kommer til å kjøre som normalt, når den har kjølt seg ned."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Påminnelse for passord"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Varsler"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Skjermdumper"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Sikkerhet"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Brukerstatus"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Generelle meldinger"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Lagring"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 4f65f63..ee04992 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -526,24 +526,15 @@
<string name="notification_importance_high" msgid="3316555356062640222">"आवाज निकाल्ने र स्क्रिनमा पपअप देखाउने"</string>
<string name="notification_more_settings" msgid="816306283396553571">"थप सेटिङहरू"</string>
<string name="notification_done" msgid="5279426047273930175">"सम्पन्न भयो"</string>
- <!-- no translation found for notification_menu_accessibility (2046162834248888553) -->
- <skip />
- <!-- no translation found for notification_menu_gear_description (2204480013726775108) -->
- <skip />
- <!-- no translation found for notification_menu_snooze_description (3653669438131034525) -->
- <skip />
- <!-- no translation found for snooze_option_15_min (1068727451405610715) -->
- <skip />
- <!-- no translation found for snooze_option_30_min (867081342535195788) -->
- <skip />
- <!-- no translation found for snooze_option_1_hour (1098086401880077154) -->
- <skip />
- <!-- no translation found for snooze_option_dont_snooze (655446566007801922) -->
- <skip />
- <!-- no translation found for snooze_undo (6074877317002985129) -->
- <skip />
- <!-- no translation found for snoozed_for_time (2390718332980204462) -->
- <skip />
+ <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
+ <string name="notification_menu_gear_description" msgid="2204480013726775108">"सूचना सम्बन्धी नियन्त्रणहरू"</string>
+ <string name="notification_menu_snooze_description" msgid="3653669438131034525">"सूचना स्नुज गर्ने विकल्पहरू"</string>
+ <string name="snooze_option_15_min" msgid="1068727451405610715">"१५ मिनेट"</string>
+ <string name="snooze_option_30_min" msgid="867081342535195788">"३० मिनेट"</string>
+ <string name="snooze_option_1_hour" msgid="1098086401880077154">"१ घण्टा"</string>
+ <string name="snooze_option_dont_snooze" msgid="655446566007801922">"स्नुज नगर्नुहोस्"</string>
+ <string name="snooze_undo" msgid="6074877317002985129">"अनडू गर्नुहोस्"</string>
+ <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> का लागि स्नुज गरियो"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"ब्याट्री उपयोग"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"चार्ज गर्ने समयमा ब्याट्री सेभर उपलब्ध छैन"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"ब्याट्री सेभर"</string>
@@ -605,24 +596,23 @@
<string name="switch_bar_on" msgid="1142437840752794229">"सक्रिय गर्नुहोस्"</string>
<string name="switch_bar_off" msgid="8803270596930432874">"निष्क्रिय"</string>
<string name="nav_bar" msgid="1993221402773877607">"नेभिगेशन पट्टी"</string>
- <!-- no translation found for nav_bar_layout (3664072994198772020) -->
- <skip />
- <!-- no translation found for nav_bar_left (731491280511316123) -->
- <skip />
- <!-- no translation found for nav_bar_right (2523774879720231974) -->
- <skip />
- <!-- no translation found for nav_bar_button_type (6947806619897153791) -->
- <skip />
- <!-- no translation found for nav_bar_default (8587114043070993007) -->
- <skip />
- <!-- no translation found for nav_bar_buttons:0 (1545641631806817203) -->
- <!-- no translation found for nav_bar_buttons:1 (5742013440802239414) -->
- <!-- no translation found for nav_bar_buttons:2 (8748101184830239843) -->
- <!-- no translation found for nav_bar_buttons:3 (8175437057325747277) -->
- <!-- no translation found for nav_bar_layouts:0 (4967898371682516967) -->
- <!-- no translation found for nav_bar_layouts:1 (6210279084134579668) -->
- <!-- no translation found for nav_bar_layouts:2 (89143234390889289) -->
- <!-- no translation found for nav_bar_layouts:3 (7715533883382410603) -->
+ <string name="nav_bar_layout" msgid="3664072994198772020">"लेआउट"</string>
+ <string name="nav_bar_left" msgid="731491280511316123">"बायाँ"</string>
+ <string name="nav_bar_right" msgid="2523774879720231974">"दायाँ"</string>
+ <string name="nav_bar_button_type" msgid="6947806619897153791">"बटनको प्रकार"</string>
+ <string name="nav_bar_default" msgid="8587114043070993007">"(पूर्वनिर्धारित)"</string>
+ <string-array name="nav_bar_buttons">
+ <item msgid="1545641631806817203">"क्लिपबोर्ड"</item>
+ <item msgid="5742013440802239414">"किकोड"</item>
+ <item msgid="8748101184830239843">"मेनु / किबोर्ड परिवर्तक"</item>
+ <item msgid="8175437057325747277">"कुनै पनि होइन"</item>
+ </string-array>
+ <string-array name="nav_bar_layouts">
+ <item msgid="4967898371682516967">"विभाजित (पूर्वनिर्धारित)"</item>
+ <item msgid="6210279084134579668">"मध्य भागमा"</item>
+ <item msgid="89143234390889289">"बायाँतिर पङ्क्तिबद्ध"</item>
+ <item msgid="7715533883382410603">"दायाँतिर पङ्क्तिबद्ध"</item>
+ </string-array>
<string name="menu_ime" msgid="4943221416525250684">"मेनु / किबोर्ड स्विचर"</string>
<string name="save" msgid="2311877285724540644">"सुरक्षित गर्नुहोस्"</string>
<string name="reset" msgid="2448168080964209908">"पुनःसेट गर्नु"</string>
@@ -630,8 +620,7 @@
<string name="clipboard" msgid="1313879395099896312">"क्लिपबोर्ड"</string>
<string name="accessibility_key" msgid="5701989859305675896">"अनुकूलनको नेभिगेशन बटन"</string>
<string name="keycode" msgid="7335281375728356499">"Keycode"</string>
- <!-- no translation found for icon (8732339849035837289) -->
- <skip />
+ <string name="icon" msgid="8732339849035837289">"आइकन"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"टाइलहरू थप्न तान्नुहोस्"</string>
<string name="drag_to_remove_tiles" msgid="3361212377437088062">"हटाउनका लागि यहाँ तान्नुहोस्"</string>
<string name="qs_edit" msgid="2232596095725105230">"सम्पादन गर्नुहोस्"</string>
@@ -682,28 +671,19 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> मध्ये पृष्ठ <xliff:g id="ID_1">%1$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"विस्तृत गर्नुहोस्"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"सानो बनाउनुहोस्"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"खारेज गर्नुहोस्"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"फोन तातो भइरहेको छ"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"फोन चिसो हुँदै गर्दा केही विशेषताहरूलाई सीमित गरिन्छ"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"तपाईंको फोन स्वतः चिसो हुने प्रयास गर्नेछ। तपाईं अझै पनि आफ्नो फोनको प्रयोग गर्न सक्नुहुन्छ तर त्यो अझ ढिलो चल्न सक्छ।\n\nचिसो भएपछि तपाईंको फोन सामान्य गतिमा चल्नेछ।"</string>
- <!-- no translation found for lockscreen_left (6806490081187499505) -->
+ <string name="lockscreen_left" msgid="6806490081187499505">"बायाँ"</string>
+ <string name="lockscreen_right" msgid="6093496261656102989">"दायाँ"</string>
+ <string name="lockscreen_customize" msgid="1288691376862981950">"सर्टकट आफू अनुकूल पार्नुहोस्"</string>
+ <string name="lockscreen_shortcut" msgid="3734369277470360642">"सर्टकट"</string>
+ <string name="lockscreen_unlock" msgid="4934466194763269051">"पासवर्ड माग्ने"</string>
+ <string name="notification_channel_alerts" msgid="4496839309318519037">"अलर्टहरू"</string>
+ <string name="notification_channel_screenshot" msgid="6314080179230000938">"स्क्रिनशटहरू"</string>
+ <!-- no translation found for notification_channel_general (4525309436693914482) -->
<skip />
- <!-- no translation found for lockscreen_right (6093496261656102989) -->
- <skip />
- <!-- no translation found for lockscreen_customize (1288691376862981950) -->
- <skip />
- <!-- no translation found for lockscreen_shortcut (3734369277470360642) -->
- <skip />
- <!-- no translation found for lockscreen_unlock (4934466194763269051) -->
- <skip />
- <!-- no translation found for notification_channel_alerts (4496839309318519037) -->
- <skip />
- <!-- no translation found for notification_channel_screenshot (6314080179230000938) -->
- <skip />
- <!-- no translation found for notification_channel_security (7345516133431326347) -->
- <skip />
- <!-- no translation found for notification_channel_user_status (1436913581465146650) -->
- <skip />
- <!-- no translation found for notification_channel_storage (3077205683020695313) -->
- <skip />
+ <string name="notification_channel_storage" msgid="3077205683020695313">"भण्डारण"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index dbb7771..f4c306a 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Pagina <xliff:g id="ID_1">%1$d</xliff:g> van <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Uitvouwen"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimaliseren"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Sluiten"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"De telefoon wordt warm"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Bepaalde functies zijn beperkt terwijl de telefoon afkoelt"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Je telefoon probeert automatisch af te koelen. Je kunt je telefoon nog steeds gebruiken, maar deze kan langzamer werken.\n\nZodra de telefoon is afgekoeld, werkt deze weer normaal."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Wachtwoordprompt"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Meldingen"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Beveiliging"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Gebruikersstatus"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Algemene berichten"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Opslag"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 008f55aa..97ec2f1 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -533,7 +533,7 @@
<string name="snooze_option_30_min" msgid="867081342535195788">"30 ਮਿੰਟ"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ਘੰਟਾ"</string>
<string name="snooze_option_dont_snooze" msgid="655446566007801922">"ਸਨੂਜ਼ ਨਾ ਕਰੋ"</string>
- <string name="snooze_undo" msgid="6074877317002985129">"ਪਹਿਲਾਂ ਵਰਗਾ ਕਰੋ"</string>
+ <string name="snooze_undo" msgid="6074877317002985129">"ਅਣਕੀਤਾ ਕਰੋ"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> ਲਈ ਸਨੂਜ਼ ਕੀਤਾ ਗਿਆ"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"ਬੈਟਰੀ ਵਰਤੋਂ"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"ਬੈਟਰੀ ਸੇਵਰ ਚਾਰਜਿੰਗ ਦੌਰਾਨ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
@@ -603,7 +603,7 @@
<string name="nav_bar_default" msgid="8587114043070993007">"(ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</string>
<string-array name="nav_bar_buttons">
<item msgid="1545641631806817203">"ਕਲਿੱਪਬੋਰਡ"</item>
- <item msgid="5742013440802239414">"ਕੀਕੋਡ"</item>
+ <item msgid="5742013440802239414">"ਕੀ-ਕੋਡ"</item>
<item msgid="8748101184830239843">"ਮੀਨੂ/ਕੀ-ਬੋਰਡ ਸਵਿੱਚਰ"</item>
<item msgid="8175437057325747277">"ਕੋਈ ਨਹੀਂ"</item>
</string-array>
@@ -620,7 +620,7 @@
<string name="clipboard" msgid="1313879395099896312">"ਕਲਿੱਪਬੋਰਡ"</string>
<string name="accessibility_key" msgid="5701989859305675896">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ ਆਵਾਗੌਣ ਬਟਨ"</string>
<string name="keycode" msgid="7335281375728356499">"ਕੀਕੋਡ"</string>
- <string name="icon" msgid="8732339849035837289">"ਚਿੰਨ੍ਹ"</string>
+ <string name="icon" msgid="8732339849035837289">"ਪ੍ਰਤੀਕ"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"ਟਾਇਲਾਂ ਨੂੰ ਸ਼ਾਮਲ ਕਰਨ ਲਈ ਘਸੀਟੋ"</string>
<string name="drag_to_remove_tiles" msgid="3361212377437088062">"ਹਟਾਉਣ ਲਈ ਇੱਥੇ ਘਸੀਟੋ"</string>
<string name="qs_edit" msgid="2232596095725105230">"ਸੰਪਾਦਨ ਕਰੋ"</string>
@@ -671,18 +671,18 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> ਦਾ <xliff:g id="ID_1">%1$d</xliff:g> ਪੰਨਾ"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"ਵਿਸਤਾਰ ਕਰੋ"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"ਛੋਟਾ ਕਰੋ"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"ਖਾਰਜ ਕਰੋ"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"ਫ਼ੋਨ ਗਰਮ ਹੋ ਰਿਹਾ ਹੈ"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"ਫ਼ੋਨ ਦੇ ਠੰਡਾ ਹੋਣ ਦੇ ਦੌਰਾਨ ਕੁਝ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਸੀਮਿਤ ਹੁੰਦੀਆਂ ਹਨ"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"ਤੁਹਾਡਾ ਫ਼ੋਨ ਸਵੈਚਲਿਤ ਰੂਪ ਵਿੱਚ ਠੰਡਾ ਹੋਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੇਗਾ। ਤੁਸੀਂ ਹਾਲੇ ਵੀ ਆਪਣੇ ਫ਼ੋਨ ਨੂੰ ਵਰਤ ਸਕਦੇ ਹੋ, ਪਰੰਤੂ ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਇਹ ਵਧੇਰੇ ਹੌਲੀ ਚੱਲੇ।\n\nਇੱਕ ਵਾਰ ਠੰਡਾ ਹੋਣ ਤੋਂ ਬਾਅਦ ਤੁਹਾਡਾ ਫ਼ੋਨ ਸਧਾਰਨ ਤੌਰ \'ਤੇ ਚੱਲੇਗਾ।"</string>
<string name="lockscreen_left" msgid="6806490081187499505">"ਖੱਬੇ"</string>
<string name="lockscreen_right" msgid="6093496261656102989">"ਸੱਜੇ"</string>
- <string name="lockscreen_customize" msgid="1288691376862981950">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ ਸ਼ਾਰਟਕੱਟ"</string>
+ <string name="lockscreen_customize" msgid="1288691376862981950">"ਸ਼ਾਰਟਕੱਟ ਨੂੰ ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ ਕਰੋ"</string>
<string name="lockscreen_shortcut" msgid="3734369277470360642">"ਸ਼ਾਰਟਕੱਟ"</string>
- <string name="lockscreen_unlock" msgid="4934466194763269051">"ਪਾਸਵਰਡ ਲਈ ਉਤਪ੍ਰੇਰਕ"</string>
+ <string name="lockscreen_unlock" msgid="4934466194763269051">"ਪਾਸਵਰਡ ਲਈ ਪੁੱਛੋ"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"ਸੁਚੇਤਨਾਵਾਂ"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"ਸਕ੍ਰੀਨਸ਼ਾਟ"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"ਸੁਰੱਖਿਆ"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"ਵਰਤੋਂਕਾਰ ਸਥਿਤੀ"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"ਆਮ ਸੁਨੇਹੇ"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"ਸਟੋਰੇਜ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 6e2d001..04efcd4 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -675,7 +675,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Strona <xliff:g id="ID_1">%1$d</xliff:g> z <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Rozwiń"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimalizuj"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Zamknij"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Telefon się nagrzewa"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Podczas obniżania temperatury telefonu niektóre funkcje są ograniczone"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefon automatycznie podejmie próbę obniżenia temperatury. Możesz go wciąż używać, ale telefon może działać wolniej.\n\nGdy temperatura się obniży, telefon będzie działał normalnie."</string>
@@ -686,7 +687,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Pytaj o hasło"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alerty"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Zrzuty ekranu"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Bezpieczeństwo"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Stan użytkownika"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Wiadomości"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Miejsce"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 4ab349c..e5a87547 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -673,7 +673,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Expandir"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Dispensar"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"O smartphone está esquentando"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Alguns recursos ficam limitados enquanto o smartphone é resfriado"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Seu smartphone tentará se resfriar automaticamente. Você ainda poderá usá-lo, mas talvez ele fique mais lento.\n\nQuando o smartphone estiver resfriado, ele voltará ao normal."</string>
@@ -684,7 +685,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Solicitar senha"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de tela"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Segurança"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Status do usuário"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Mensagens gerais"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Armazenamento"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index fa1f70e..4304d99 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Expandir"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Ignorar"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"O telemóvel está a aquecer"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Algumas funcionalidades são limitadas enquanto o telemóvel arrefece"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"O telemóvel tenta arrefecer automaticamente. Pode continuar a utilizá-lo, mas este poderá funcionar mais lentamente.\n\nAssim que o telemóvel tiver arrefecido, funcionará normalmente."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Solicitar palavra-passe"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de ecrã"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Segurança"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Estado do utilizador"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Mensagens gerais"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Armazenamento"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 4ab349c..e5a87547 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -673,7 +673,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Expandir"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Dispensar"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"O smartphone está esquentando"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Alguns recursos ficam limitados enquanto o smartphone é resfriado"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Seu smartphone tentará se resfriar automaticamente. Você ainda poderá usá-lo, mas talvez ele fique mais lento.\n\nQuando o smartphone estiver resfriado, ele voltará ao normal."</string>
@@ -684,7 +685,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Solicitar senha"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de tela"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Segurança"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Status do usuário"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Mensagens gerais"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Armazenamento"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 7dc39d5..535b5c3 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -675,7 +675,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Pagina <xliff:g id="ID_1">%1$d</xliff:g> din <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Extindeți"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizați"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Respingeți"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Telefonul se încălzește"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Anumite funcții sunt limitate în timp ce telefonul se răcește"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefonul va încerca automat să se răcească. Puteți folosi telefonul în continuare, dar este posibil să funcționeze mai lent.\n\nDupă ce se răcește, telefonul va funcționa normal."</string>
@@ -686,7 +687,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Solicitați parola"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alerte"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturi de ecran"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Securitate"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Stare utilizator"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Mesaje generale"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Stocare"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 5806e23..68d499d 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -677,7 +677,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Страница <xliff:g id="ID_1">%1$d</xliff:g> из <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Развернуть"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Свернуть"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Закрыть"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Телефон нагревается"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Пока телефон не остынет, некоторые функции могут быть недоступны."</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Ваш телефон остынет автоматически.\n\nОбратите внимание, что до тех пор он может работать медленнее, чем обычно."</string>
@@ -688,7 +689,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Подсказка для пароля"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Уведомления"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Скриншоты"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Безопасность"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Статус пользователя"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Сообщения"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Хранилище"</string>
</resources>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 8870fad..9c58ba1 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> න් <xliff:g id="ID_1">%1$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"දිග හරින්න"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"කුඩා කරන්න"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"අස් කරන්න"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"දුරකථනය උණුසුම් වෙමින්"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"දුරකථනය සිසිල් වන අතරතුර සමහර විශේෂාංග සීමිත විය හැකිය"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"ඔබගේ දුරකථනය ස්වයංක්රියව සිසිල් වීමට උත්සාහ කරනු ඇත. ඔබට තවම ඔබේ දුරකථනය භාවිත කළ හැකිය, නමුත් එය සෙමින් ධාවනය විය හැකිය.\n\nඔබේ දුරකථනය සිසිල් වූ පසු, එය සාමාන්ය ලෙස ධාවනය වනු ඇත."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"මුරපදය සඳහා ප්රේරණය කරන්න"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"ඇඟවීම්"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"තිර රු"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"ආරක්ෂාව"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"පරිශීලක තත්ත්වය"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"පොදු පණිවිඩ"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"ගබඩාව"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 8afa432..cddcaf0 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -677,7 +677,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Strana <xliff:g id="ID_1">%1$d</xliff:g> z <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Rozbaliť"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimalizovať"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Odmietnuť"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Teplota telefónu stúpa"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Niektoré funkcie budú obmedzené, dokým neklesne teplota telefónu"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Váš telefón sa automaticky pokúsi schladiť. Môžete ho naďalej používať, ale môže fungovať pomalšie.\n\nPo poklese teploty bude telefón fungovať ako normálne."</string>
@@ -688,7 +689,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Požadovať heslo"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Upozornenia"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Snímky obrazovky"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Zabezpečenie"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Stav používateľa"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Všeobecné správy"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Úložisko"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index f457847..da993b4 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -677,7 +677,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>. stran od <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Razširi"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimiraj"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Opusti"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Telefon se segreva"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Nekatere funkcije bodo med ohlajanjem omejene."</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefon se bo samodejno poskusil ohladiti. Še naprej ga lahko uporabljate, vendar bo morda deloval počasneje.\n\nKo se telefon ohladi, bo zopet deloval kot običajno."</string>
@@ -688,7 +689,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Poziv za geslo"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Opozorila"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Posnetki zaslona"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Varnost"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Stanje uporabnika"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Splošna sporočila"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Shramba"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index b7409a0..6b8bb97 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Faqja <xliff:g id="ID_1">%1$d</xliff:g> nga <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Zgjero"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizo"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Hiqe"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Telefoni po bëhet i ngrohtë"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Disa funksione janë të kufizuara kur telefoni është duke u ftohur"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefoni yt do të përpiqet automatikisht që të ftohet. Mund ta përdorësh përsëri telefonin, por ai mund të punojë më ngadalë.\n\nPasi telefoni të jetë ftohur, ai do të punojë si normalisht."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Kërko fjalëkalimin"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Sinjalizimet"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Pamjet e ekranit"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Siguria"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Statusi i përdoruesit"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Mesazhe të përgjithshme"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Hapësira ruajtëse"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 4b0a577..0af49e4e 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -673,7 +673,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>. страна од <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Прошири"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Умањи"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Одбаци"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Телефон се загрејао"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Неке функције су ограничене док се телефон не охлади"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Телефон ће аутоматски покушати да се охлади. И даље ћете моћи да користите телефон, али ће спорије реаговати.\n\nКада се телефон охлади, нормално ће радити."</string>
@@ -684,7 +685,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Упит за лозинку"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Обавештења"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Снимци екрана"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Безбедност"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Статус корисника"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Опште поруке"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Меморијски простор"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index c119da7..9700f0a 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Sida <xliff:g id="ID_1">%1$d</xliff:g> av <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Utöka"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimera"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Ignorera"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Mobilen börjar bli varm"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Vissa funktioner är begränsade medan mobilen svalnar"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Mobilen försöker svalna automatiskt. Du kan fortfarande använda mobilen, men den kan vara långsammare än vanligt.\n\nMobilen fungerar som vanligt när den har svalnat."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Kräv lösenord"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Varningar"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Skärmdumpar"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Säkerhet"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Användarstatus"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Allmänna meddelanden"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Lagring"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 54fc4431..fc9439c 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -467,13 +467,13 @@
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Gonga ili ukomeshe. Huenda ikakomesha huduma za zana za walio na matatizo ya kuona au kusikia."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Inaonyesha %s ya vidhibiti vya sauti. Telezesha kidole juu ili uondoe."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Imeficha vidhibiti vya sauti"</string>
- <string name="system_ui_tuner" msgid="708224127392452018">"Kipokea Ishara cha SystemUI"</string>
+ <string name="system_ui_tuner" msgid="708224127392452018">"Kirekebishi cha kiolesura cha mfumo"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Onyesha asilimia ya betri iliyopachikwa"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Onyesha asilimia ya kiwango cha betri ndani ya aikoni ya sehemu ya arifa inapokuwa haichaji"</string>
<string name="quick_settings" msgid="10042998191725428">"Mipangilio ya Haraka"</string>
<string name="status_bar" msgid="4877645476959324760">"Sehemu ya kuonyesha hali"</string>
<string name="overview" msgid="4018602013895926956">"Muhtasari"</string>
- <string name="demo_mode" msgid="2532177350215638026">"Hali ya onyesho la UI ya mfumo"</string>
+ <string name="demo_mode" msgid="2532177350215638026">"Hali ya onyesho la kirekebishi cha kiolesura cha mfumo"</string>
<string name="enable_demo_mode" msgid="4844205668718636518">"Washa hali ya onyesho"</string>
<string name="show_demo_mode" msgid="2018336697782464029">"Onyesha hali ya onyesho"</string>
<string name="status_bar_ethernet" msgid="5044290963549500128">"Ethaneti"</string>
@@ -490,12 +490,12 @@
<string name="accessibility_status_bar_hotspot" msgid="4099381329956402865">"Mtandao-hewa"</string>
<string name="accessibility_managed_profile" msgid="6613641363112584120">"Wasifu wa kazini"</string>
<string name="tuner_warning_title" msgid="7094689930793031682">"Kinafurahisha kwa baadhi ya watu lakini si wote"</string>
- <string name="tuner_warning" msgid="8730648121973575701">"Kipokea Ishara cha System UI kinakupa njia zaidi za kugeuza na kubadilisha kiolesura cha Android ili kikufae. Vipengele hivi vya majaribio vinaweza kubadilika, kuharibika, au kupotea katika matoleo ya siku zijazo. Endelea kwa uangalifu."</string>
+ <string name="tuner_warning" msgid="8730648121973575701">"Kirekebishi cha kiolesura cha mfumo kinakupa njia zaidi za kugeuza na kubadilisha kiolesura cha Android ili kikufae. Vipengele hivi vya majaribio vinaweza kubadilika, kuharibika au kupotea katika matoleo ya siku zijazo. Endelea kwa uangalifu."</string>
<string name="tuner_persistent_warning" msgid="8597333795565621795">"Vipengele hivi vya majaribio vinaweza kubadilika, kuharibika, au kupotea katika matoleo ya siku zijazo. Endelea kwa uangalifu."</string>
<string name="got_it" msgid="2239653834387972602">"Nimeelewa"</string>
- <string name="tuner_toast" msgid="603429811084428439">"Hongera! Kipokea Ishara cha System UI kimeongezwa kwenye Mipangilio"</string>
+ <string name="tuner_toast" msgid="603429811084428439">"Hongera! Kirekebishi cha kiolesura cha mfumo kimeongezwa kwenye mipangilio"</string>
<string name="remove_from_settings" msgid="8389591916603406378">"Ondoa kwenye Mipangilio"</string>
- <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Je, ungependa kuondoa Kipokea ishara cha SystemUI kwenye Mipangilio na uache kutumia vipengele vyake vyote?"</string>
+ <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Je, ungependa kuondoa Kirekebishi cha kiolesura cha mfumo kwenye mipangilio na uache kutumia vipengele vyake vyote?"</string>
<string name="activity_not_found" msgid="348423244327799974">"Programu haijasakinishwa kwenye kifaa chako"</string>
<string name="clock_seconds" msgid="7689554147579179507">"Onyesha sekunde za saa"</string>
<string name="clock_seconds_desc" msgid="6282693067130470675">"Onyesha sekunde za saa katika sehemu ya arifa. Inaweza kuathiri muda wa matumizi ya betri."</string>
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Ukurasa wa <xliff:g id="ID_1">%1$d</xliff:g> kati ya <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Panua"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Punguza"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Ondoa"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Joto la simu linaongezeka"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Baadhi ya vipengele havitatumika kwenye simu wakati inapoa"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Simu yako itajaribu kupoa kiotomatiki. Bado unaweza kutumia simu yako, lakini huenda ikafanya kazi polepole. \n\nPindi simu yako itakapopoa, itaendelea kufanya kazi kama kawaida."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Omba nenosiri"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Arifa"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Picha za skrini"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Usalama"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Hali ya mtumiaji"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Ujumbe wa Jumla"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Hifadhi"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 68b99bf..b79e8a9 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"பக்கம் <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"விரி"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"சிறிதாக்கு"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"நிராகரி"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"மொபைல் சூடாகிறது"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"மொபைலின் வெப்ப அளவு குறையும் போது, சில அம்சங்களைப் பயன்படுத்த முடியாது"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"உங்கள் மொபைலின் வெப்ப அளவு தானாகவே குறையும். தொடர்ந்து நீங்கள் மொபைலைப் பயன்படுத்தலாம், ஆனால் அதன் வேகம் குறைவாக இருக்கக்கூடும்.\n\nமொபைலின் வெப்ப அளவு குறைந்தவுடன், அது இயல்பு நிலையில் இயங்கும்."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"கடவுச்சொல்லைக் கேள்"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"விழிப்பூட்டல்கள்"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"ஸ்கிரீன் ஷாட்டுகள்"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"பாதுகாப்பு"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"பயனர் நிலை"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"பொதுச் செய்திகள்"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"சேமிப்பிடம்"</string>
</resources>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 69619bd0..2175c5a 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -600,7 +600,7 @@
<string name="nav_bar_left" msgid="731491280511316123">"ఎడమ"</string>
<string name="nav_bar_right" msgid="2523774879720231974">"కుడి"</string>
<string name="nav_bar_button_type" msgid="6947806619897153791">"బటన్ రకం"</string>
- <string name="nav_bar_default" msgid="8587114043070993007">"(yadha prakaram)"</string>
+ <string name="nav_bar_default" msgid="8587114043070993007">"(డిఫాల్ట్)"</string>
<string-array name="nav_bar_buttons">
<item msgid="1545641631806817203">"క్లిప్బోర్డ్"</item>
<item msgid="5742013440802239414">"కీకోడ్"</item>
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g>లో <xliff:g id="ID_1">%1$d</xliff:g>వ పేజీ"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"విస్తరింపజేయి"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"కనిష్టీకరించు"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"తీసివేయి"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"ఫోన్ వేడెక్కుతోంది"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"ఫోన్ను చల్లబరిచే క్రమంలో కొన్ని లక్షణాలు పరిమితం చేయబడ్డాయి"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"మీ ఫోన్ స్వయంచాలకంగా చల్లబడటానికి ప్రయత్నిస్తుంది. మీరు ఇప్పటికీ మీ ఫోన్ను ఉపయోగించవచ్చు, కానీ దాని పనితీరు నెమ్మదిగా ఉండవచ్చు.\n\nమీ ఫోన్ చల్లబడిన తర్వాత, అది సాధారణ రీతిలో పని చేస్తుంది."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"పాస్వర్డ్ కోసం ప్రాంప్ట్ చేయి"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"హెచ్చరికలు"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"స్క్రీన్షాట్లు"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"భద్రత"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"వినియోగదారు స్థితి"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"సాధారణ సందేశాలు"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"నిల్వ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index ce7af3c..e4d489d2 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"หน้า <xliff:g id="ID_1">%1$d</xliff:g> จาก <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"ขยาย"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"ย่อเล็กสุด"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"ปิด"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"โทรศัพท์เริ่มเครื่องร้อน"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"คุณลักษณะบางอย่างจะใช้งานได้จำกัดขณะโทรศัพท์ลดอุณหภูมิลง"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"โทรศัพท์จะพยายามลดอุณหภูมิลงโดยอัตโนมัติ คุณยังสามารถใช้โทรศัพท์ได้ แต่โทรศัพท์อาจทำงานช้าลง\n\nโทรศัพท์จะทำงานตามปกติเมื่อเย็นลงแล้ว"</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"แจ้งให้ป้อนรหัสผ่าน"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"การแจ้งเตือน"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"ภาพหน้าจอ"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"ความปลอดภัย"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"สถานะของผู้ใช้"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"ข้อความทั่วไป"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"พื้นที่เก็บข้อมูล"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 3e632c4..ac5aa92 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Page <xliff:g id="ID_1">%1$d</xliff:g> ng <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Palawakin"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"I-minimize"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"I-dismiss"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Umiinit ang telepono"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Limitado ang ilang feature habang nagku-cool down ang telepono"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Awtomatikong susubukan ng iyong telepono na mag-cool down. Magagamit mo pa rin ang iyong telepono, ngunit maaaring mas mabagal ang paggana nito.\n\nKapag nakapag-cool down na ang iyong telepono, gagana na ito nang normal."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Mag-prompt para sa password"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Mga Alerto"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Mga Screenshot"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Seguridad"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Status ng user"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Mga Pangkalahatang Mensahe"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Storage"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 3d00f1d..8cf0633 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Sayfa <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Genişlet"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Simge durumuna getir"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Kapat"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Telefon ısınıyor"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Telefon soğurken bazı özellikler sınırlı olarak kullanılabilir"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefonunuz otomatik olarak soğumaya çalışacak. Bu sırada telefonunuzu kullanmaya devam edebilirsiniz ancak uygulamalar daha yavaş çalışabilir.\n\nTelefonunuz soğuduktan sonra normal şekilde çalışacaktır."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Şifre sor"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Uyarılar"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Ekran görüntüleri"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Güvenlik"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Kullanıcı durumu"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Genel Mesajlar"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Depolama alanı"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 4d928d9..62c0c8c0 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -677,7 +677,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Сторінка <xliff:g id="ID_1">%1$d</xliff:g> з <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Розгорнути"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Згорнути"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Вимкнути"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Телефон нагрівається"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Під час охолодження деякі функції обмежуються"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Ваш телефон охолоджуватиметься автоматично. Ви можете далі користуватися телефоном, але він може працювати повільніше.\n\nКоли телефон охолоне, він працюватиме належним чином."</string>
@@ -688,7 +689,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Запит пароля"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Сповіщення"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Знімки екрана"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Безпека"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Статус користувача"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Загальні повідомлення"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Пам’ять"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index d8ab5f8..9a7629b 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -526,24 +526,15 @@
<string name="notification_importance_high" msgid="3316555356062640222">"آواز نکالیں اور اسکرین پر پاپ کریں"</string>
<string name="notification_more_settings" msgid="816306283396553571">"مزید ترتیبات"</string>
<string name="notification_done" msgid="5279426047273930175">"ہوگیا"</string>
- <!-- no translation found for notification_menu_accessibility (2046162834248888553) -->
- <skip />
- <!-- no translation found for notification_menu_gear_description (2204480013726775108) -->
- <skip />
- <!-- no translation found for notification_menu_snooze_description (3653669438131034525) -->
- <skip />
- <!-- no translation found for snooze_option_15_min (1068727451405610715) -->
- <skip />
- <!-- no translation found for snooze_option_30_min (867081342535195788) -->
- <skip />
- <!-- no translation found for snooze_option_1_hour (1098086401880077154) -->
- <skip />
- <!-- no translation found for snooze_option_dont_snooze (655446566007801922) -->
- <skip />
- <!-- no translation found for snooze_undo (6074877317002985129) -->
- <skip />
- <!-- no translation found for snoozed_for_time (2390718332980204462) -->
- <skip />
+ <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
+ <string name="notification_menu_gear_description" msgid="2204480013726775108">"اطلاع کے کنٹرولز"</string>
+ <string name="notification_menu_snooze_description" msgid="3653669438131034525">"اطلاع اسنوز کرنے کے اختیارات"</string>
+ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 منٹ"</string>
+ <string name="snooze_option_30_min" msgid="867081342535195788">"30 منٹ"</string>
+ <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 گھنٹہ"</string>
+ <string name="snooze_option_dont_snooze" msgid="655446566007801922">"اسنوز نہ کريں"</string>
+ <string name="snooze_undo" msgid="6074877317002985129">"کالعدم کریں"</string>
+ <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> کیلئے اسنوز کیا گیا"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"بیٹری کا استعمال"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"چارجنگ کے دوران بیٹری سیور دستیاب نہیں ہے"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"بیٹری سیور"</string>
@@ -605,24 +596,23 @@
<string name="switch_bar_on" msgid="1142437840752794229">"آن"</string>
<string name="switch_bar_off" msgid="8803270596930432874">"آف"</string>
<string name="nav_bar" msgid="1993221402773877607">"نیویگیشن بار"</string>
- <!-- no translation found for nav_bar_layout (3664072994198772020) -->
- <skip />
- <!-- no translation found for nav_bar_left (731491280511316123) -->
- <skip />
- <!-- no translation found for nav_bar_right (2523774879720231974) -->
- <skip />
- <!-- no translation found for nav_bar_button_type (6947806619897153791) -->
- <skip />
- <!-- no translation found for nav_bar_default (8587114043070993007) -->
- <skip />
- <!-- no translation found for nav_bar_buttons:0 (1545641631806817203) -->
- <!-- no translation found for nav_bar_buttons:1 (5742013440802239414) -->
- <!-- no translation found for nav_bar_buttons:2 (8748101184830239843) -->
- <!-- no translation found for nav_bar_buttons:3 (8175437057325747277) -->
- <!-- no translation found for nav_bar_layouts:0 (4967898371682516967) -->
- <!-- no translation found for nav_bar_layouts:1 (6210279084134579668) -->
- <!-- no translation found for nav_bar_layouts:2 (89143234390889289) -->
- <!-- no translation found for nav_bar_layouts:3 (7715533883382410603) -->
+ <string name="nav_bar_layout" msgid="3664072994198772020">"لے آؤٹ"</string>
+ <string name="nav_bar_left" msgid="731491280511316123">"بائیں"</string>
+ <string name="nav_bar_right" msgid="2523774879720231974">"دائیں"</string>
+ <string name="nav_bar_button_type" msgid="6947806619897153791">"بٹن کی قسم"</string>
+ <string name="nav_bar_default" msgid="8587114043070993007">"(ڈیفالٹ)"</string>
+ <string-array name="nav_bar_buttons">
+ <item msgid="1545641631806817203">"کلپ بورڈ"</item>
+ <item msgid="5742013440802239414">"کی کوڈ"</item>
+ <item msgid="8748101184830239843">"مینو/ کی بورڈ سوئچر"</item>
+ <item msgid="8175437057325747277">"کوئی نہیں"</item>
+ </string-array>
+ <string-array name="nav_bar_layouts">
+ <item msgid="4967898371682516967">"تقسیم شدہ (ڈیفالٹ)"</item>
+ <item msgid="6210279084134579668">"بیچوں بیچ"</item>
+ <item msgid="89143234390889289">"بائیں جانب موافق کردہ"</item>
+ <item msgid="7715533883382410603">"دائیں جانب موافق کردہ"</item>
+ </string-array>
<string name="menu_ime" msgid="4943221416525250684">"مینو/ کی بورڈ سوئچر"</string>
<string name="save" msgid="2311877285724540644">"محفوظ کریں"</string>
<string name="reset" msgid="2448168080964209908">"دوبارہ ترتیب دیں"</string>
@@ -630,8 +620,7 @@
<string name="clipboard" msgid="1313879395099896312">"کلپ بورڈ"</string>
<string name="accessibility_key" msgid="5701989859305675896">"حسب ضرورت نیویگیشن بٹن"</string>
<string name="keycode" msgid="7335281375728356499">"کی کوڈ"</string>
- <!-- no translation found for icon (8732339849035837289) -->
- <skip />
+ <string name="icon" msgid="8732339849035837289">"آئیکن"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"ٹائٹلز شامل کرنے کیلئے گھسیٹیں"</string>
<string name="drag_to_remove_tiles" msgid="3361212377437088062">"ہٹانے کیلئے یہاں گھسیٹیں؟"</string>
<string name="qs_edit" msgid="2232596095725105230">"ترمیم کریں"</string>
@@ -682,28 +671,19 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"صفحہ <xliff:g id="ID_1">%1$d</xliff:g> از <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"پھیلائیں"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"چھوٹی کریں"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"برخاست کریں"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"فون گرم ہو رہا ہے"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"فون کے ٹھنڈے ہو جانے تک کچھ خصوصیات محدود ہیں"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"آپ کا فون خودکار طور پر ٹھنڈا ہونے کی کوشش کرے گا۔ آپ ابھی بھی اپنا فون استعمال کر سکتے ہیں، مگر ہو سکتا ہے یہ سست چلے۔\n\nایک بار آپ کا فون ٹھنڈا ہوجائے تو یہ معمول کے مطابق چلے گا۔"</string>
- <!-- no translation found for lockscreen_left (6806490081187499505) -->
+ <string name="lockscreen_left" msgid="6806490081187499505">"بائیں"</string>
+ <string name="lockscreen_right" msgid="6093496261656102989">"دائیں"</string>
+ <string name="lockscreen_customize" msgid="1288691376862981950">"شارٹ کٹ کو حسب ضرورت بنائیں"</string>
+ <string name="lockscreen_shortcut" msgid="3734369277470360642">"شارٹ کٹ"</string>
+ <string name="lockscreen_unlock" msgid="4934466194763269051">"پاسورڈ کا اشارہ"</string>
+ <string name="notification_channel_alerts" msgid="4496839309318519037">"الرٹس"</string>
+ <string name="notification_channel_screenshot" msgid="6314080179230000938">"اسکرین شاٹس"</string>
+ <!-- no translation found for notification_channel_general (4525309436693914482) -->
<skip />
- <!-- no translation found for lockscreen_right (6093496261656102989) -->
- <skip />
- <!-- no translation found for lockscreen_customize (1288691376862981950) -->
- <skip />
- <!-- no translation found for lockscreen_shortcut (3734369277470360642) -->
- <skip />
- <!-- no translation found for lockscreen_unlock (4934466194763269051) -->
- <skip />
- <!-- no translation found for notification_channel_alerts (4496839309318519037) -->
- <skip />
- <!-- no translation found for notification_channel_screenshot (6314080179230000938) -->
- <skip />
- <!-- no translation found for notification_channel_security (7345516133431326347) -->
- <skip />
- <!-- no translation found for notification_channel_user_status (1436913581465146650) -->
- <skip />
- <!-- no translation found for notification_channel_storage (3077205683020695313) -->
- <skip />
+ <string name="notification_channel_storage" msgid="3077205683020695313">"اسٹوریج"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index f72092b..f6df9068 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -529,14 +529,14 @@
<string name="notification_more_settings" msgid="816306283396553571">"Boshqa sozlamalar"</string>
<string name="notification_done" msgid="5279426047273930175">"Tayyor"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
- <string name="notification_menu_gear_description" msgid="2204480013726775108">"bildirishnomalarni boshqarish elementlari"</string>
+ <string name="notification_menu_gear_description" msgid="2204480013726775108">"bildirishnoma sozlamalari"</string>
<string name="notification_menu_snooze_description" msgid="3653669438131034525">"bildirishnomalarni kechiktirish parametrlari"</string>
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 daqiqa"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 daqiqa"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 soat"</string>
<string name="snooze_option_dont_snooze" msgid="655446566007801922">"Kechiktirilmasin"</string>
<string name="snooze_undo" msgid="6074877317002985129">"BEKOR QILISH"</string>
- <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> kechiktirildi"</string>
+ <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> muddatga kechiktirildi"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Batareya sarfi"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Quvvat tejash rejimidan quvvatlash vaqtida foydalanib bo‘lmaydi"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Quvvat tejash rejimi"</string>
@@ -606,12 +606,12 @@
<string-array name="nav_bar_buttons">
<item msgid="1545641631806817203">"Vaqtinchalik xotira"</item>
<item msgid="5742013440802239414">"Tugma kodi"</item>
- <item msgid="8748101184830239843">"Menyu yoki klaviatura"</item>
- <item msgid="8175437057325747277">"Hech qaysi"</item>
+ <item msgid="8748101184830239843">"Menyu/klaviaturani almashtirish"</item>
+ <item msgid="8175437057325747277">"Hech biri"</item>
</string-array>
<string-array name="nav_bar_layouts">
- <item msgid="4967898371682516967">"Bo‘lingan (standart)"</item>
- <item msgid="6210279084134579668">"O‘rtaga tekislangan"</item>
+ <item msgid="4967898371682516967">"Alohida (standart)"</item>
+ <item msgid="6210279084134579668">"Markazda"</item>
<item msgid="89143234390889289">"Chapga tekislangan"</item>
<item msgid="7715533883382410603">"O‘ngga tekislangan"</item>
</string-array>
@@ -673,7 +673,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>-sahifa, jami: <xliff:g id="ID_2">%2$d</xliff:g> ta sahifa"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Yoyish"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Yig‘ish"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Yopish"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Telefon qizib ketdi"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Telefon sovish paytida ayrim funksiyalar ishlamasligi mumkin"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefon avtomatik ravishda o‘zini sovitadi. Telefoningizdan foydalanishda davom etishingiz mumkin, lekin u sekinroq ishlashi mumkin.\n\nTelefon sovishi bilan normal holatda ishlashni boshlaydi."</string>
@@ -684,7 +685,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Parol uchun bildirgi"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Ogohlantirishlar"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Skrinshotlar"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Xavfsizlik"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Foydalanuvchi holati"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Umumiy xabarlar"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Xotira"</string>
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index e33328a..ce5d46f 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -673,7 +673,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Trang <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Mở rộng"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Thu nhỏ"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Loại bỏ"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Điện thoại đang nóng lên"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Một số tính năng bị hạn chế trong khi điện thoại nguội dần"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Điện thoại của bạn sẽ tự động nguội dần. Bạn vẫn có thể sử dụng điện thoại, nhưng điện thoại có thể chạy chậm hơn. \n\nSau khi đã nguội, điện thoại sẽ chạy bình thường."</string>
@@ -684,7 +685,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Lời nhắc nhập mật khẩu"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Cảnh báo"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Ảnh chụp màn hình"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Bảo mật"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Trạng thái người dùng"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Thông báo chung"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Bộ nhớ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index f754c38..d0c9e001 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"第 <xliff:g id="ID_1">%1$d</xliff:g> 页,共 <xliff:g id="ID_2">%2$d</xliff:g> 页"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"展开"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"最小化"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"关闭"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"手机温度上升中"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"手机降温时,部分功能的使用会受限制"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"您的手机将自动尝试降温。您依然可以使用您的手机,但是手机运行速度可能会更慢。\n\n手机降温后,就会恢复正常的运行速度。"</string>
@@ -682,7 +683,7 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"提示输入密码"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"提醒"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"屏幕截图"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"安全性"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"用户状态"</string>
+ <!-- no translation found for notification_channel_general (4525309436693914482) -->
+ <skip />
<string name="notification_channel_storage" msgid="3077205683020695313">"存储空间"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index ca882ab..f7bf78e 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -673,7 +673,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"第 <xliff:g id="ID_1">%1$d</xliff:g> 頁 (共 <xliff:g id="ID_2">%2$d</xliff:g> 頁)"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"展開"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"最小化"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"關閉"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"手機溫度正在上升"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"手機降溫時,部分功能會受限制"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"手機會自動嘗試降溫。您仍可以使用手機,但手機的運作速度可能較慢。\n\n手機降溫後便會恢復正常。"</string>
@@ -684,7 +685,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"輸入密碼提示"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"通知"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"螢幕擷取畫面"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"安全性"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"使用者狀態"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"一般訊息"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"儲存空間"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 82ef5ee..54ef0a64 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"第 <xliff:g id="ID_1">%1$d</xliff:g> 頁,共 <xliff:g id="ID_2">%2$d</xliff:g> 頁"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"展開"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"最小化"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"關閉"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"手機變熱"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"手機降溫時,部分功能會受限"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"手機會自動嘗試降溫。你仍可繼續使用手機,但是手機的運作速度可能會較慢。\n\n手機降溫完畢後,就會恢復正常的運作速度。"</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"提示輸入密碼"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"快訊"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"螢幕擷取畫面"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"安全性"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"使用者狀態"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"一般訊息"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"儲存空間"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 1a6b8d0..7858962 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -671,7 +671,8 @@
<string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Ikhasi <xliff:g id="ID_1">%1$d</xliff:g> kwangu-<xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="pip_phone_expand" msgid="5889780005575693909">"Nweba"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Nciphisa"</string>
- <string name="pip_phone_dismiss" msgid="1305916715402775904">"Cashisa"</string>
+ <!-- no translation found for pip_phone_close (8416647892889710330) -->
+ <skip />
<string name="high_temp_title" msgid="4589508026407318374">"Ifoni iyafudumala"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Ezinye izici zikhawulelwe ngenkathi ifoni iphola"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Ifoni yakho izozama ngokuzenzakalela ukuphola. Ungasasebenzisa ifoni yakho, kodwa ingasebenza ngokungasheshi.\n\nUma ifoni yakho isipholile, izosebenza ngokuvamile."</string>
@@ -682,7 +683,6 @@
<string name="lockscreen_unlock" msgid="4934466194763269051">"Yalela iphasiwedi"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Izexwayiso"</string>
<string name="notification_channel_screenshot" msgid="6314080179230000938">"Izithombe-skrini"</string>
- <string name="notification_channel_security" msgid="7345516133431326347">"Ukuphepha"</string>
- <string name="notification_channel_user_status" msgid="1436913581465146650">"Isimo somsebenzisi"</string>
+ <string name="notification_channel_general" msgid="4525309436693914482">"Imilayezo ejwayelekile"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Isitoreji"</string>
</resources>
diff --git a/packages/SystemUI/res/values/arrays.xml b/packages/SystemUI/res/values/arrays.xml
deleted file mode 100644
index bf0cba2..0000000
--- a/packages/SystemUI/res/values/arrays.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* //device/apps/common/assets/res/any/colors.xml
-**
-** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- BatteryMeterView parameters -->
- <array name="batterymeter_color_levels">
- <item>15</item>
- <item>100</item>
- </array>
- <array name="batterymeter_color_values">
- <item>@*android:color/battery_saver_mode_color</item>
- <item>#FFFFFFFF</item>
- </array>
- <array name="batterymeter_bolt_points">
- <item>73</item> <item>0</item>
- <item>392</item><item>0</item>
- <item>201</item><item>259</item>
- <item>442</item><item>259</item>
- <item>4</item> <item>703</item>
- <item>157</item><item>334</item>
- <item>0</item> <item>334</item>
- </array>
- <array name="batterymeter_plus_points">
- <item>3</item><item>0</item>
- <item>5</item><item>0</item>
- <item>5</item><item>3</item>
- <item>8</item><item>3</item>
- <item>8</item><item>5</item>
- <item>5</item><item>5</item>
- <item>5</item><item>8</item>
- <item>3</item><item>8</item>
- <item>3</item><item>5</item>
- <item>0</item><item>5</item>
- <item>0</item><item>3</item>
- <item>3</item><item>3</item>
- </array>
-</resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index ad5b108..1249f44 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -26,9 +26,6 @@
<drawable name="status_bar_notification_row_background_color">#ff090909</drawable>
<color name="notification_list_shadow_top">#80000000</color>
<drawable name="heads_up_notification_bg_pressed">#ff33B5E5</drawable>
- <color name="batterymeter_frame_color">#4DFFFFFF</color><!-- 30% white -->
- <color name="batterymeter_charge_color">#FFFFFFFF</color>
- <color name="batterymeter_bolt_color">#FFFFFFFF</color>
<color name="qs_batterymeter_frame_color">#FF404040</color>
<color name="system_warning_color">@*android:color/system_error</color>
<color name="qs_tile_divider">#29ffffff</color><!-- 16% white -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index b768f90..e69c4a3 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -520,14 +520,6 @@
<!-- How much two taps can be apart to still be recognized as a double tap on the lockscreen -->
<dimen name="double_tap_slop">32dp</dimen>
- <!-- Margin on the right side of the system icon group on Keyguard. -->
- <fraction name="battery_button_height_fraction">10.5%</fraction>
-
- <!-- Fraction value to smooth the edges of the battery icon. The path will be inset by this
- fraction of a pixel.-->
- <fraction name="battery_subpixel_smoothing_left">0%</fraction>
- <fraction name="battery_subpixel_smoothing_right">0%</fraction>
-
<dimen name="battery_margin_bottom">0dp</dimen>
<!-- Padding at the end of the view that displays the mobile signal icons. If the view is
@@ -642,9 +634,6 @@
<dimen name="docked_divider_handle_width">16dp</dimen>
<dimen name="docked_divider_handle_height">2dp</dimen>
- <dimen name="battery_height">14.5dp</dimen>
- <dimen name="battery_width">9.5dp</dimen>
-
<dimen name="battery_detail_graph_space_top">27dp</dimen>
<dimen name="battery_detail_graph_space_bottom">27dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 8553952..f7cf444 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -819,9 +819,6 @@
<!-- Expanded Status Bar Header: Not charging [CHAR LIMIT=40] -->
<string name="expanded_header_battery_not_charging">Not charging</string>
- <!-- Glyph to be overlaid atop the battery when the level is extremely low. Do not translate. -->
- <string name="battery_meter_very_low_overlay_symbol">!</string>
-
<!-- Shows up when there is a user SSL CA Cert installed on the
device. Indicates to the user that SSL traffic can be intercepted.
If the text fits on one line (~14 chars), it should start with a
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java
old mode 100755
new mode 100644
index 5a6afca..9068079
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java
@@ -16,169 +16,40 @@
package com.android.systemui;
-import android.animation.ArgbEvaluator;
-import android.annotation.Nullable;
import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
import android.database.ContentObserver;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.ColorFilter;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.RectF;
-import android.graphics.Typeface;
-import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Handler;
import android.provider.Settings;
-
+import com.android.settingslib.graph.BatteryMeterDrawableBase;
import com.android.systemui.statusbar.policy.BatteryController;
-public class BatteryMeterDrawable extends Drawable implements
+public class BatteryMeterDrawable extends BatteryMeterDrawableBase implements
BatteryController.BatteryStateChangeCallback {
- private static final float ASPECT_RATIO = 9.5f / 14.5f;
- public static final String TAG = BatteryMeterDrawable.class.getSimpleName();
public static final String SHOW_PERCENT_SETTING = "status_bar_show_battery_percent";
- private static final boolean SINGLE_DIGIT_PERCENT = false;
-
- private static final int FULL = 96;
-
- private static final float BOLT_LEVEL_THRESHOLD = 0.3f; // opaque bolt below this fraction
-
- private final int[] mColors;
- private final int mIntrinsicWidth;
- private final int mIntrinsicHeight;
-
- private boolean mShowPercent;
- private float mButtonHeightFraction;
- private float mSubpixelSmoothingLeft;
- private float mSubpixelSmoothingRight;
- private final Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint, mBoltPaint,
- mPlusPaint;
- private float mTextHeight, mWarningTextHeight;
- private int mIconTint = Color.WHITE;
- private float mOldDarkIntensity = 0f;
-
- private int mHeight;
- private int mWidth;
- private String mWarningString;
- private final int mCriticalLevel;
- private int mChargeColor;
- private final float[] mBoltPoints;
- private final Path mBoltPath = new Path();
- private final float[] mPlusPoints;
- private final Path mPlusPath = new Path();
-
- private final RectF mFrame = new RectF();
- private final RectF mButtonFrame = new RectF();
- private final RectF mBoltFrame = new RectF();
- private final RectF mPlusFrame = new RectF();
-
- private final Path mShapePath = new Path();
- private final Path mClipPath = new Path();
- private final Path mTextPath = new Path();
-
private BatteryController mBatteryController;
- private boolean mPowerSaveEnabled;
-
- private int mDarkModeBackgroundColor;
- private int mDarkModeFillColor;
-
- private int mLightModeBackgroundColor;
- private int mLightModeFillColor;
-
- private final SettingObserver mSettingObserver;
-
- private final Context mContext;
-
- private int mLevel = -1;
- private boolean mPluggedIn;
- private boolean mListening;
+ private SettingObserver mSettingObserver;
public BatteryMeterDrawable(Context context, int frameColor) {
- mContext = context;
+ super(context, frameColor);
+
mSettingObserver = new SettingObserver(new Handler(mContext.getMainLooper()));
- final Resources res = context.getResources();
- TypedArray levels = res.obtainTypedArray(R.array.batterymeter_color_levels);
- TypedArray colors = res.obtainTypedArray(R.array.batterymeter_color_values);
-
- final int N = levels.length();
- mColors = new int[2*N];
- for (int i=0; i<N; i++) {
- mColors[2*i] = levels.getInt(i, 0);
- mColors[2*i+1] = colors.getColor(i, 0);
- }
- levels.recycle();
- colors.recycle();
- updateShowPercent();
- mWarningString = context.getString(R.string.battery_meter_very_low_overlay_symbol);
- mCriticalLevel = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_criticalBatteryWarningLevel);
- mButtonHeightFraction = context.getResources().getFraction(
- R.fraction.battery_button_height_fraction, 1, 1);
- mSubpixelSmoothingLeft = context.getResources().getFraction(
- R.fraction.battery_subpixel_smoothing_left, 1, 1);
- mSubpixelSmoothingRight = context.getResources().getFraction(
- R.fraction.battery_subpixel_smoothing_right, 1, 1);
-
- mFramePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mFramePaint.setColor(frameColor);
- mFramePaint.setDither(true);
- mFramePaint.setStrokeWidth(0);
- mFramePaint.setStyle(Paint.Style.FILL_AND_STROKE);
-
- mBatteryPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mBatteryPaint.setDither(true);
- mBatteryPaint.setStrokeWidth(0);
- mBatteryPaint.setStyle(Paint.Style.FILL_AND_STROKE);
-
- mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- Typeface font = Typeface.create("sans-serif-condensed", Typeface.BOLD);
- mTextPaint.setTypeface(font);
- mTextPaint.setTextAlign(Paint.Align.CENTER);
-
- mWarningTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mWarningTextPaint.setColor(mColors[1]);
- font = Typeface.create("sans-serif", Typeface.BOLD);
- mWarningTextPaint.setTypeface(font);
- mWarningTextPaint.setTextAlign(Paint.Align.CENTER);
-
- mChargeColor = context.getColor(R.color.batterymeter_charge_color);
-
- mBoltPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mBoltPaint.setColor(context.getColor(R.color.batterymeter_bolt_color));
- mBoltPoints = loadBoltPoints(res);
-
- mPlusPaint = new Paint(mBoltPaint);
- mPlusPoints = loadPlusPoints(res);
-
- mDarkModeBackgroundColor =
- context.getColor(R.color.dark_mode_icon_color_dual_tone_background);
- mDarkModeFillColor = context.getColor(R.color.dark_mode_icon_color_dual_tone_fill);
- mLightModeBackgroundColor =
- context.getColor(R.color.light_mode_icon_color_dual_tone_background);
- mLightModeFillColor = context.getColor(R.color.light_mode_icon_color_dual_tone_fill);
-
- mIntrinsicWidth = context.getResources().getDimensionPixelSize(R.dimen.battery_width);
- mIntrinsicHeight = context.getResources().getDimensionPixelSize(R.dimen.battery_height);
}
@Override
- public int getIntrinsicHeight() {
- return mIntrinsicHeight;
+ public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
+ setBatteryLevel(level);
+ setPluggedIn(pluggedIn);
}
@Override
- public int getIntrinsicWidth() {
- return mIntrinsicWidth;
+ public void onPowerSaveChanged(boolean isPowerSave) {
+ setPowerSave(isPowerSave);
}
public void startListening() {
- mListening = true;
mContext.getContentResolver().registerContentObserver(
Settings.System.getUriFor(SHOW_PERCENT_SETTING), false, mSettingObserver);
updateShowPercent();
@@ -186,326 +57,18 @@
}
public void stopListening() {
- mListening = false;
mContext.getContentResolver().unregisterContentObserver(mSettingObserver);
mBatteryController.removeCallback(this);
}
- public void disableShowPercent() {
- mShowPercent = false;
- postInvalidate();
- }
-
- private void postInvalidate() {
- scheduleSelf(this::invalidateSelf, 0);
+ protected void updateShowPercent() {
+ setShowPercent(0 != Settings.System.getInt(mContext.getContentResolver(),
+ SHOW_PERCENT_SETTING, 0));
}
public void setBatteryController(BatteryController batteryController) {
mBatteryController = batteryController;
- mPowerSaveEnabled = mBatteryController.isPowerSave();
- }
-
- @Override
- public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
- mLevel = level;
- mPluggedIn = pluggedIn;
-
- postInvalidate();
- }
-
- @Override
- public void onPowerSaveChanged(boolean isPowerSave) {
- mPowerSaveEnabled = isPowerSave;
- invalidateSelf();
- }
-
- private static float[] loadBoltPoints(Resources res) {
- final int[] pts = res.getIntArray(R.array.batterymeter_bolt_points);
- int maxX = 0, maxY = 0;
- for (int i = 0; i < pts.length; i += 2) {
- maxX = Math.max(maxX, pts[i]);
- maxY = Math.max(maxY, pts[i + 1]);
- }
- final float[] ptsF = new float[pts.length];
- for (int i = 0; i < pts.length; i += 2) {
- ptsF[i] = (float)pts[i] / maxX;
- ptsF[i + 1] = (float)pts[i + 1] / maxY;
- }
- return ptsF;
- }
-
- private static float[] loadPlusPoints(Resources res) {
- final int[] pts = res.getIntArray(R.array.batterymeter_plus_points);
- int maxX = 0, maxY = 0;
- for (int i = 0; i < pts.length; i += 2) {
- maxX = Math.max(maxX, pts[i]);
- maxY = Math.max(maxY, pts[i + 1]);
- }
- final float[] ptsF = new float[pts.length];
- for (int i = 0; i < pts.length; i += 2) {
- ptsF[i] = (float)pts[i] / maxX;
- ptsF[i + 1] = (float)pts[i + 1] / maxY;
- }
- return ptsF;
- }
-
- @Override
- public void setBounds(int left, int top, int right, int bottom) {
- super.setBounds(left, top, right, bottom);
- mHeight = bottom - top;
- mWidth = right - left;
- mWarningTextPaint.setTextSize(mHeight * 0.75f);
- mWarningTextHeight = -mWarningTextPaint.getFontMetrics().ascent;
- }
-
- private void updateShowPercent() {
- mShowPercent = 0 != Settings.System.getInt(mContext.getContentResolver(),
- SHOW_PERCENT_SETTING, 0);
- }
-
- private int getColorForLevel(int percent) {
-
- // If we are in power save mode, always use the normal color.
- if (mPowerSaveEnabled) {
- return mColors[mColors.length-1];
- }
- int thresh, color = 0;
- for (int i=0; i<mColors.length; i+=2) {
- thresh = mColors[i];
- color = mColors[i+1];
- if (percent <= thresh) {
-
- // Respect tinting for "normal" level
- if (i == mColors.length-2) {
- return mIconTint;
- } else {
- return color;
- }
- }
- }
- return color;
- }
-
- public void setDarkIntensity(float darkIntensity) {
- if (darkIntensity == mOldDarkIntensity) {
- return;
- }
- int backgroundColor = getBackgroundColor(darkIntensity);
- int fillColor = getFillColor(darkIntensity);
- setColors(fillColor, backgroundColor);
- mOldDarkIntensity = darkIntensity;
- }
-
- public void setColors(int fillColor, int backgroundColor) {
- mIconTint = fillColor;
- mFramePaint.setColor(backgroundColor);
- mBoltPaint.setColor(fillColor);
- mChargeColor = fillColor;
- invalidateSelf();
- }
-
- private int getBackgroundColor(float darkIntensity) {
- return getColorForDarkIntensity(
- darkIntensity, mLightModeBackgroundColor, mDarkModeBackgroundColor);
- }
-
- private int getFillColor(float darkIntensity) {
- return getColorForDarkIntensity(
- darkIntensity, mLightModeFillColor, mDarkModeFillColor);
- }
-
- private int getColorForDarkIntensity(float darkIntensity, int lightColor, int darkColor) {
- return (int) ArgbEvaluator.getInstance().evaluate(darkIntensity, lightColor, darkColor);
- }
-
- @Override
- public void draw(Canvas c) {
- final int level = mLevel;
-
- if (level == -1) return;
-
- float drawFrac = (float) level / 100f;
- final int height = mHeight;
- final int width = (int) (ASPECT_RATIO * mHeight);
- int px = (mWidth - width) / 2;
-
- final int buttonHeight = (int) (height * mButtonHeightFraction);
-
- mFrame.set(0, 0, width, height);
- mFrame.offset(px, 0);
-
- // button-frame: area above the battery body
- mButtonFrame.set(
- mFrame.left + Math.round(width * 0.25f),
- mFrame.top,
- mFrame.right - Math.round(width * 0.25f),
- mFrame.top + buttonHeight);
-
- mButtonFrame.top += mSubpixelSmoothingLeft;
- mButtonFrame.left += mSubpixelSmoothingLeft;
- mButtonFrame.right -= mSubpixelSmoothingRight;
-
- // frame: battery body area
- mFrame.top += buttonHeight;
- mFrame.left += mSubpixelSmoothingLeft;
- mFrame.top += mSubpixelSmoothingLeft;
- mFrame.right -= mSubpixelSmoothingRight;
- mFrame.bottom -= mSubpixelSmoothingRight;
-
- // set the battery charging color
- mBatteryPaint.setColor(mPluggedIn ? mChargeColor : getColorForLevel(level));
-
- if (level >= FULL) {
- drawFrac = 1f;
- } else if (level <= mCriticalLevel) {
- drawFrac = 0f;
- }
-
- final float levelTop = drawFrac == 1f ? mButtonFrame.top
- : (mFrame.top + (mFrame.height() * (1f - drawFrac)));
-
- // define the battery shape
- mShapePath.reset();
- mShapePath.moveTo(mButtonFrame.left, mButtonFrame.top);
- mShapePath.lineTo(mButtonFrame.right, mButtonFrame.top);
- mShapePath.lineTo(mButtonFrame.right, mFrame.top);
- mShapePath.lineTo(mFrame.right, mFrame.top);
- mShapePath.lineTo(mFrame.right, mFrame.bottom);
- mShapePath.lineTo(mFrame.left, mFrame.bottom);
- mShapePath.lineTo(mFrame.left, mFrame.top);
- mShapePath.lineTo(mButtonFrame.left, mFrame.top);
- mShapePath.lineTo(mButtonFrame.left, mButtonFrame.top);
-
- if (mPluggedIn) {
- // define the bolt shape
- final float bl = mFrame.left + mFrame.width() / 4f;
- final float bt = mFrame.top + mFrame.height() / 6f;
- final float br = mFrame.right - mFrame.width() / 4f;
- final float bb = mFrame.bottom - mFrame.height() / 10f;
- if (mBoltFrame.left != bl || mBoltFrame.top != bt
- || mBoltFrame.right != br || mBoltFrame.bottom != bb) {
- mBoltFrame.set(bl, bt, br, bb);
- mBoltPath.reset();
- mBoltPath.moveTo(
- mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(),
- mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height());
- for (int i = 2; i < mBoltPoints.length; i += 2) {
- mBoltPath.lineTo(
- mBoltFrame.left + mBoltPoints[i] * mBoltFrame.width(),
- mBoltFrame.top + mBoltPoints[i + 1] * mBoltFrame.height());
- }
- mBoltPath.lineTo(
- mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(),
- mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height());
- }
-
- float boltPct = (mBoltFrame.bottom - levelTop) / (mBoltFrame.bottom - mBoltFrame.top);
- boltPct = Math.min(Math.max(boltPct, 0), 1);
- if (boltPct <= BOLT_LEVEL_THRESHOLD) {
- // draw the bolt if opaque
- c.drawPath(mBoltPath, mBoltPaint);
- } else {
- // otherwise cut the bolt out of the overall shape
- mShapePath.op(mBoltPath, Path.Op.DIFFERENCE);
- }
- } else if (mPowerSaveEnabled) {
- // define the plus shape
- final float pw = mFrame.width() * 2 / 3;
- final float pl = mFrame.left + (mFrame.width() - pw) / 2;
- final float pt = mFrame.top + (mFrame.height() - pw) / 2;
- final float pr = mFrame.right - (mFrame.width() - pw) / 2;
- final float pb = mFrame.bottom - (mFrame.height() - pw) / 2;
- if (mPlusFrame.left != pl || mPlusFrame.top != pt
- || mPlusFrame.right != pr || mPlusFrame.bottom != pb) {
- mPlusFrame.set(pl, pt, pr, pb);
- mPlusPath.reset();
- mPlusPath.moveTo(
- mPlusFrame.left + mPlusPoints[0] * mPlusFrame.width(),
- mPlusFrame.top + mPlusPoints[1] * mPlusFrame.height());
- for (int i = 2; i < mPlusPoints.length; i += 2) {
- mPlusPath.lineTo(
- mPlusFrame.left + mPlusPoints[i] * mPlusFrame.width(),
- mPlusFrame.top + mPlusPoints[i + 1] * mPlusFrame.height());
- }
- mPlusPath.lineTo(
- mPlusFrame.left + mPlusPoints[0] * mPlusFrame.width(),
- mPlusFrame.top + mPlusPoints[1] * mPlusFrame.height());
- }
-
- float boltPct = (mPlusFrame.bottom - levelTop) / (mPlusFrame.bottom - mPlusFrame.top);
- boltPct = Math.min(Math.max(boltPct, 0), 1);
- if (boltPct <= BOLT_LEVEL_THRESHOLD) {
- // draw the bolt if opaque
- c.drawPath(mPlusPath, mPlusPaint);
- } else {
- // otherwise cut the bolt out of the overall shape
- mShapePath.op(mPlusPath, Path.Op.DIFFERENCE);
- }
- }
-
- // compute percentage text
- boolean pctOpaque = false;
- float pctX = 0, pctY = 0;
- String pctText = null;
- if (!mPluggedIn && !mPowerSaveEnabled && level > mCriticalLevel && mShowPercent) {
- mTextPaint.setColor(getColorForLevel(level));
- mTextPaint.setTextSize(height *
- (SINGLE_DIGIT_PERCENT ? 0.75f
- : (mLevel == 100 ? 0.38f : 0.5f)));
- mTextHeight = -mTextPaint.getFontMetrics().ascent;
- pctText = String.valueOf(SINGLE_DIGIT_PERCENT ? (level/10) : level);
- pctX = mWidth * 0.5f;
- pctY = (mHeight + mTextHeight) * 0.47f;
- pctOpaque = levelTop > pctY;
- if (!pctOpaque) {
- mTextPath.reset();
- mTextPaint.getTextPath(pctText, 0, pctText.length(), pctX, pctY, mTextPath);
- // cut the percentage text out of the overall shape
- mShapePath.op(mTextPath, Path.Op.DIFFERENCE);
- }
- }
-
- // draw the battery shape background
- c.drawPath(mShapePath, mFramePaint);
-
- // draw the battery shape, clipped to charging level
- mFrame.top = levelTop;
- mClipPath.reset();
- mClipPath.addRect(mFrame, Path.Direction.CCW);
- mShapePath.op(mClipPath, Path.Op.INTERSECT);
- c.drawPath(mShapePath, mBatteryPaint);
-
- if (!mPluggedIn && !mPowerSaveEnabled) {
- if (level <= mCriticalLevel) {
- // draw the warning text
- final float x = mWidth * 0.5f;
- final float y = (mHeight + mWarningTextHeight) * 0.48f;
- c.drawText(mWarningString, x, y, mWarningTextPaint);
- } else if (pctOpaque) {
- // draw the percentage text
- c.drawText(pctText, pctX, pctY, mTextPaint);
- }
- }
- }
-
- // Some stuff required by Drawable.
- @Override
- public void setAlpha(int alpha) {
- }
-
- @Override
- public void setColorFilter(@Nullable ColorFilter colorFilter) {
- mFramePaint.setColorFilter(colorFilter);
- mBatteryPaint.setColorFilter(colorFilter);
- mWarningTextPaint.setColorFilter(colorFilter);
- mTextPaint.setColorFilter(colorFilter);
- mBoltPaint.setColorFilter(colorFilter);
- mPlusPaint.setColorFilter(colorFilter);
- }
-
- @Override
- public int getOpacity() {
- return 0;
+ setPowerSave(mBatteryController.isPowerSave());
}
private final class SettingObserver extends ContentObserver {
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 29a8da0..69e3874 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -16,18 +16,29 @@
package com.android.systemui;
import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
import android.content.res.TypedArray;
+import android.graphics.Rect;
import android.util.ArraySet;
import android.util.AttributeSet;
+import android.util.TypedValue;
import android.view.View;
import android.widget.ImageView;
+import android.widget.LinearLayout;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerService.Tunable;
public class BatteryMeterView extends ImageView implements
- BatteryController.BatteryStateChangeCallback, TunerService.Tunable {
+ BatteryStateChangeCallback, Tunable, DarkReceiver, ConfigurationListener {
private final BatteryMeterDrawable mDrawable;
private final String mSlotBattery;
@@ -77,6 +88,7 @@
mBatteryController.addCallback(this);
mDrawable.startListening();
Dependency.get(TunerService.class).addTunable(this, StatusBarIconController.ICON_BLACKLIST);
+ Dependency.get(ConfigurationController.class).addCallback(this);
}
@Override
@@ -85,6 +97,7 @@
mBatteryController.removeCallback(this);
mDrawable.stopListening();
Dependency.get(TunerService.class).removeTunable(this);
+ Dependency.get(ConfigurationController.class).removeCallback(this);
}
@Override
@@ -99,8 +112,35 @@
}
- public void setDarkIntensity(float f) {
- mDrawable.setDarkIntensity(f);
+ @Override
+ public void onDensityOrFontScaleChanged() {
+ scaleBatteryMeterViews();
+ }
+
+ /**
+ * Looks up the scale factor for status bar icons and scales the battery view by that amount.
+ */
+ private void scaleBatteryMeterViews() {
+ Resources res = getContext().getResources();
+ TypedValue typedValue = new TypedValue();
+
+ res.getValue(R.dimen.status_bar_icon_scale_factor, typedValue, true);
+ float iconScaleFactor = typedValue.getFloat();
+
+ int batteryHeight = res.getDimensionPixelSize(R.dimen.status_bar_battery_icon_height);
+ int batteryWidth = res.getDimensionPixelSize(R.dimen.status_bar_battery_icon_width);
+ int marginBottom = res.getDimensionPixelSize(R.dimen.battery_margin_bottom);
+
+ LinearLayout.LayoutParams scaledLayoutParams = new LinearLayout.LayoutParams(
+ (int) (batteryWidth * iconScaleFactor), (int) (batteryHeight * iconScaleFactor));
+ scaledLayoutParams.setMarginsRelative(0, 0, 0, marginBottom);
+
+ setLayoutParams(scaledLayoutParams);
+ }
+
+ @Override
+ public void onDarkChanged(Rect area, float darkIntensity, int tint) {
+ mDrawable.setDarkIntensity(DarkIconDispatcher.isInArea(area, this) ? darkIntensity : 0);
}
public void setRawColors(int fgColor, int bgColor) {
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index e1f3176..1d4a093 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -25,8 +25,13 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
+import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
import com.android.systemui.statusbar.phone.ManagedProfileController;
import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
+import com.android.systemui.statusbar.phone.StatusBarWindowManager;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl;
import com.android.systemui.statusbar.policy.AccessibilityController;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryControllerImpl;
@@ -34,6 +39,8 @@
import com.android.systemui.statusbar.policy.BluetoothControllerImpl;
import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.CastControllerImpl;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
@@ -183,6 +190,18 @@
mProviders.put(TunerService.class.getName(), () ->
new TunerService(mContext));
+ mProviders.put(StatusBarWindowManager.class.getName(), () ->
+ new StatusBarWindowManager(mContext));
+
+ mProviders.put(DarkIconDispatcher.class.getName(), () ->
+ new DarkIconDispatcherImpl(mContext));
+
+ mProviders.put(ConfigurationController.class.getName(), () ->
+ new ConfigurationControllerImpl(mContext));
+
+ mProviders.put(StatusBarIconController.class.getName(), () ->
+ new StatusBarIconControllerImpl(mContext));
+
// Put all dependencies above here so the factory can override them if it wants.
SystemUIFactory.getInstance().injectDependencies(mProviders, mContext);
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 27070ed..e5bda7e 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -27,6 +27,7 @@
import android.os.Process;
import android.os.SystemProperties;
import android.os.UserHandle;
+import android.util.ArraySet;
import android.util.Log;
import com.android.systemui.fragments.FragmentService;
@@ -43,6 +44,7 @@
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.StatusBarWindowManager;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.usb.StorageNotification;
import com.android.systemui.util.NotificationChannels;
@@ -149,7 +151,6 @@
* Makes sure that all the SystemUI services are running. If they are already running, this is a
* no-op. This is needed to conditinally start all the services, as we only need to have it in
* the main process.
- *
* <p>This method must only be called from the main thread.</p>
*/
public void startServicesIfNeeded() {
@@ -160,7 +161,6 @@
* Ensures that all the Secondary user SystemUI services are running. If they are already
* running, this is a no-op. This is needed to conditinally start all the services, as we only
* need to have it in the main process.
- *
* <p>This method must only be called from the main thread.</p>
*/
void startSecondaryUserServicesIfNeeded() {
@@ -184,7 +184,7 @@
Log.v(TAG, "Starting SystemUI services for user " +
Process.myUserHandle().getIdentifier() + ".");
final int N = services.length;
- for (int i=0; i<N; i++) {
+ for (int i = 0; i < N; i++) {
Class<?> cl = services[i];
if (DEBUG) Log.d(TAG, "loading: " + cl);
try {
@@ -207,15 +207,34 @@
}
Dependency.get(PluginManager.class).addPluginListener(OverlayPlugin.ACTION,
new PluginListener<OverlayPlugin>() {
- @Override
- public void onPluginConnected(OverlayPlugin plugin, Context pluginContext) {
- StatusBar statusBar = getComponent(StatusBar.class);
- if (statusBar != null) {
- plugin.setup(statusBar.getStatusBarWindow(),
- statusBar.getNavigationBarView());
- }
- }
- }, OverlayPlugin.VERSION, true /* Allow multiple plugins */);
+ private ArraySet<OverlayPlugin> mOverlays;
+
+ @Override
+ public void onPluginConnected(OverlayPlugin plugin, Context pluginContext) {
+ StatusBar statusBar = getComponent(StatusBar.class);
+ if (statusBar != null) {
+ plugin.setup(statusBar.getStatusBarWindow(),
+ statusBar.getNavigationBarView());
+ }
+ // Lazy init.
+ if (mOverlays == null) mOverlays = new ArraySet<>();
+ if (plugin.holdStatusBarOpen()) {
+ mOverlays.add(plugin);
+ Dependency.get(StatusBarWindowManager.class).setStateListener(b ->
+ mOverlays.forEach(o -> o.setCollapseDesired(b)));
+ Dependency.get(StatusBarWindowManager.class).setForcePluginOpen(
+ mOverlays.size() != 0);
+
+ }
+ }
+
+ @Override
+ public void onPluginDisconnected(OverlayPlugin plugin) {
+ mOverlays.remove(plugin);
+ Dependency.get(StatusBarWindowManager.class).setForcePluginOpen(
+ mOverlays.size() != 0);
+ }
+ }, OverlayPlugin.VERSION, true /* Allow multiple plugins */);
mServicesStarted = true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
index 50506a9..0c6bf52 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
@@ -97,7 +97,7 @@
return p;
}
- public void addTagListener(String tag, FragmentListener listener) {
+ public FragmentHostManager addTagListener(String tag, FragmentListener listener) {
ArrayList<FragmentListener> listeners = mListeners.get(tag);
if (listeners == null) {
listeners = new ArrayList<>();
@@ -108,6 +108,7 @@
if (current != null && current.getView() != null) {
listener.onFragmentViewCreated(tag, current);
}
+ return this;
}
// Shouldn't generally be needed, included for completeness sake.
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 99c8c6b..cbe822f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1956,11 +1956,11 @@
}
public StatusBarKeyguardViewManager registerStatusBar(StatusBar statusBar,
- ViewGroup container, StatusBarWindowManager statusBarWindowManager,
+ ViewGroup container,
ScrimController scrimController,
FingerprintUnlockController fingerprintUnlockController) {
mStatusBarKeyguardViewManager.registerStatusBar(statusBar, container,
- statusBarWindowManager, scrimController, fingerprintUnlockController,
+ scrimController, fingerprintUnlockController,
mDismissCallbackRegistry);
return mStatusBarKeyguardViewManager;
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
index beec137..0259e3e 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
@@ -25,11 +25,14 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnLayoutChangeListener;
+import android.view.ViewGroup;
import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
import android.widget.FrameLayout;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.recents.misc.SystemServicesProxy;
public class PipDismissViewController {
@@ -65,8 +68,10 @@
public void createDismissTarget() {
if (mDismissView == null) {
// Determine sizes for the gradient
- Point windowSize = new Point();
- mWindowManager.getDefaultDisplay().getSize(windowSize);
+ final Rect stableInsets = new Rect();
+ SystemServicesProxy.getInstance(mContext).getStableInsets(stableInsets);
+ final Point windowSize = new Point();
+ mWindowManager.getDefaultDisplay().getRealSize(windowSize);
mMinHeight = windowSize.y * DISMISS_GRADIENT_MIN_HEIGHT_PERCENT;
mMaxHeight = windowSize.y * DISMISS_GRADIENT_MAX_HEIGHT_PERCENT;
@@ -74,13 +79,16 @@
LayoutInflater inflater = LayoutInflater.from(mContext);
mDismissView = inflater.inflate(R.layout.pip_dismiss_view, null);
mGradientView = mDismissView.findViewById(R.id.gradient_view);
- FrameLayout.LayoutParams glp = (android.widget.FrameLayout.LayoutParams) mGradientView
- .getLayoutParams();
+ FrameLayout.LayoutParams glp =
+ (FrameLayout.LayoutParams) mGradientView.getLayoutParams();
glp.height = (int) mMaxHeight;
mGradientView.setLayoutParams(glp);
mGradientView.setPivotY(windowSize.y);
mGradientView.setScaleY(mMaxHeight / mMinHeight); // Set to min height via scaling
mDismissContainer = mDismissView.findViewById(R.id.pip_dismiss_container);
+ FrameLayout.LayoutParams clp =
+ (FrameLayout.LayoutParams) mDismissContainer.getLayoutParams();
+ clp.bottomMargin = stableInsets.bottom;
mDismissContainer.addOnLayoutChangeListener(new OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom,
@@ -92,15 +100,16 @@
});
// Add the target to the window
- WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- windowSize.x,
- (int) mMaxHeight,
- WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG,
- WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
- | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
+ LayoutParams lp = new LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, (int) mMaxHeight,
+ 0, windowSize.y - (int) mMaxHeight,
+ LayoutParams.TYPE_SYSTEM_DIALOG,
+ LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | LayoutParams.FLAG_LAYOUT_NO_LIMITS
+ | LayoutParams.FLAG_NOT_TOUCHABLE
+ | LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
- lp.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
+ lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
mWindowManager.addView(mDismissView, lp);
}
mDismissView.animate().cancel();
@@ -132,7 +141,7 @@
.withEndAction(new Runnable() {
@Override
public void run() {
- mWindowManager.removeView(mDismissView);
+ mWindowManager.removeViewImmediate(mDismissView);
mDismissView = null;
}
})
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java
index 5a665a9..3a4caa9 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java
@@ -83,9 +83,7 @@
private MediaController.Callback mPlaybackChangedListener = new MediaController.Callback() {
@Override
public void onPlaybackStateChanged(PlaybackState state) {
- if (!mListeners.isEmpty()) {
- notifyActionsChanged(getMediaActions());
- }
+ notifyActionsChanged();
}
};
@@ -146,9 +144,9 @@
boolean isPlaying = MediaSession.isActiveState(state);
long actions = mMediaController.getPlaybackState().getActions();
if (!isPlaying && ((actions & PlaybackState.ACTION_PLAY) != 0)) {
- mediaActions.add(mPauseAction);
- } else if (isPlaying && ((actions & PlaybackState.ACTION_PAUSE) != 0)) {
mediaActions.add(mPlayAction);
+ } else if (isPlaying && ((actions & PlaybackState.ACTION_PAUSE) != 0)) {
+ mediaActions.add(mPauseAction);
}
return mediaActions;
}
@@ -202,9 +200,7 @@
if (controller != null) {
controller.registerCallback(mPlaybackChangedListener);
}
- if (!mListeners.isEmpty()) {
- notifyActionsChanged(getMediaActions());
- }
+ notifyActionsChanged();
// TODO(winsonc): Consider if we want to close the PIP after a timeout (like on TV)
}
@@ -213,8 +209,9 @@
/**
* Notifies all listeners that the actions have changed.
*/
- private void notifyActionsChanged(List<RemoteAction> actions) {
+ private void notifyActionsChanged() {
if (!mListeners.isEmpty()) {
+ List<RemoteAction> actions = getMediaActions();
mListeners.forEach(l -> l.onMediaActionsChanged(actions));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index 3d36868..471c3ae 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -34,6 +34,7 @@
import android.text.format.DateUtils;
import android.util.Log;
import android.util.Slog;
+import com.android.internal.logging.MetricsLogger;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -45,6 +46,8 @@
static final String TAG = "PowerUI";
static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final long TEMPERATURE_INTERVAL = 30 * DateUtils.SECOND_IN_MILLIS;
+ private static final long TEMPERATURE_LOGGING_INTERVAL = DateUtils.HOUR_IN_MILLIS;
+ private static final int MAX_RECENT_TEMPS = 125; // TEMPERATURE_LOGGING_INTERVAL plus a buffer
private final Handler mHandler = new Handler();
private final Receiver mReceiver = new Receiver();
@@ -62,7 +65,10 @@
private long mScreenOffTime = -1;
- private float mThrottlingTemp;
+ private float mThresholdTemp;
+ private float[] mRecentTemps = new float[MAX_RECENT_TEMPS];
+ private int mNumTemps;
+ private long mNextLogTime;
public void start() {
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
@@ -229,10 +235,10 @@
return;
}
- mThrottlingTemp = Settings.Global.getFloat(resolver, Settings.Global.WARNING_TEMPERATURE,
+ mThresholdTemp = Settings.Global.getFloat(resolver, Settings.Global.WARNING_TEMPERATURE,
resources.getInteger(R.integer.config_warningTemperature));
- if (mThrottlingTemp < 0f) {
+ if (mThresholdTemp < 0f) {
// Get the throttling temperature. No need to check if we're not throttling.
float[] throttlingTemps = mHardwarePropertiesManager.getDeviceTemperatures(
HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN,
@@ -242,41 +248,86 @@
|| throttlingTemps[0] == HardwarePropertiesManager.UNDEFINED_TEMPERATURE) {
return;
}
- mThrottlingTemp = throttlingTemps[0];
+ mThresholdTemp = throttlingTemps[0];
}
+ setNextLogTime();
// We have passed all of the checks, start checking the temp
updateTemperatureWarning();
}
private void updateTemperatureWarning() {
- StatusBar statusBar = getComponent(StatusBar.class);
- if (statusBar != null && statusBar.isDeviceInVrMode()) {
- // ensure the warning isn't showing, since VR shows its own warning
- mWarnings.dismissTemperatureWarning();
- } else {
- float[] temps = mHardwarePropertiesManager.getDeviceTemperatures(
- HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN,
- HardwarePropertiesManager.TEMPERATURE_CURRENT);
- boolean shouldShowTempWarning = false;
- for (float temp : temps) {
- if (temp >= mThrottlingTemp) {
- Slog.i(TAG, "currentTemp=" + temp + ", throttlingTemp=" + mThrottlingTemp);
- shouldShowTempWarning = true;
- break;
- }
- }
- if (shouldShowTempWarning) {
+ float[] temps = mHardwarePropertiesManager.getDeviceTemperatures(
+ HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN,
+ HardwarePropertiesManager.TEMPERATURE_CURRENT);
+ if (temps.length != 0) {
+ float temp = temps[0];
+ mRecentTemps[mNumTemps++] = temp;
+
+ StatusBar statusBar = getComponent(StatusBar.class);
+ if (statusBar != null && !statusBar.isDeviceInVrMode()
+ && temp >= mThresholdTemp) {
+ logAtTemperatureThreshold(temp);
mWarnings.showTemperatureWarning();
} else {
mWarnings.dismissTemperatureWarning();
}
}
- // TODO: skip this when in VR mode since we already get a callback
+ logTemperatureStats();
+
mHandler.postDelayed(this::updateTemperatureWarning, TEMPERATURE_INTERVAL);
}
+ private void logAtTemperatureThreshold(float temp) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("currentTemp=").append(temp)
+ .append(",thresholdTemp=").append(mThresholdTemp)
+ .append(",batteryStatus=").append(mBatteryStatus)
+ .append(",recentTemps=");
+ for (int i = 0; i < mNumTemps; i++) {
+ sb.append(mRecentTemps[i]).append(',');
+ }
+ Slog.i(TAG, sb.toString());
+ }
+
+ /**
+ * Calculates and logs min, max, and average
+ * {@link HardwarePropertiesManager#DEVICE_TEMPERATURE_SKIN} over the past
+ * {@link #TEMPERATURE_LOGGING_INTERVAL}.
+ */
+ private void logTemperatureStats() {
+ if (mNextLogTime > System.currentTimeMillis() && mNumTemps != MAX_RECENT_TEMPS) {
+ return;
+ }
+
+ if (mNumTemps > 0) {
+ float sum = mRecentTemps[0], min = mRecentTemps[0], max = mRecentTemps[0];
+ for (int i = 1; i < mNumTemps; i++) {
+ float temp = mRecentTemps[i];
+ sum += temp;
+ if (temp > max) {
+ max = temp;
+ }
+ if (temp < min) {
+ min = temp;
+ }
+ }
+
+ float avg = sum / mNumTemps;
+ Slog.i(TAG, "avg=" + avg + ",min=" + min + ",max=" + max);
+ MetricsLogger.histogram(mContext, "device_skin_temp_avg", (int) avg);
+ MetricsLogger.histogram(mContext, "device_skin_temp_min", (int) min);
+ MetricsLogger.histogram(mContext, "device_skin_temp_max", (int) max);
+ }
+ setNextLogTime();
+ mNumTemps = 0;
+ }
+
+ private void setNextLogTime() {
+ mNextLogTime = System.currentTimeMillis() + TEMPERATURE_LOGGING_INTERVAL;
+ }
+
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.print("mLowBatteryAlertCloseLevel=");
pw.println(mLowBatteryAlertCloseLevel);
@@ -303,8 +354,10 @@
Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0));
pw.print("bucket: ");
pw.println(Integer.toString(findBatteryLevelBucket(mBatteryLevel)));
- pw.print("mThrottlingTemp=");
- pw.println(Float.toString(mThrottlingTemp));
+ pw.print("mThresholdTemp=");
+ pw.println(Float.toString(mThresholdTemp));
+ pw.print("mNextLogTime=");
+ pw.println(Long.toString(mNextLogTime));
mWarnings.dump(pw);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
index 6f1f977..fff8305 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
@@ -197,7 +197,7 @@
}
mDrawable.onBatteryLevelChanged(100, false, false);
mDrawable.onPowerSaveChanged(true);
- mDrawable.disableShowPercent();
+ mDrawable.setShowPercent(false);
((ImageView) mCurrentView.findViewById(android.R.id.icon)).setImageDrawable(mDrawable);
Checkable checkbox = (Checkable) mCurrentView.findViewById(android.R.id.toggle);
checkbox.setChecked(mPowerSave);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index a4cd14d..b48b829 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -179,7 +179,7 @@
}
@Override
- public void onKeyguardChanged() {
+ public void onKeyguardShowingChanged() {
refreshState();
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index 5374f18..423a1df 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -141,7 +141,7 @@
}
@Override
- public void onKeyguardChanged() {
+ public void onKeyguardShowingChanged() {
refreshState();
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 8091199..55491b2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -656,6 +656,10 @@
synchronized (mHeaderBarLock) {
if (mHeaderBar.getMeasuredWidth() != taskViewWidth ||
mHeaderBar.getMeasuredHeight() != mTaskBarHeight) {
+ if (mDummyStackView.useGridLayout()) {
+ mHeaderBar.setShouldDarkenBackgroundColor(true);
+ mHeaderBar.setNoUserInteractionState();
+ }
mHeaderBar.forceLayout();
mHeaderBar.measure(
MeasureSpec.makeMeasureSpec(taskViewWidth, MeasureSpec.EXACTLY),
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 45e766c..9a52a7b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -151,7 +151,7 @@
@ViewDebug.ExportedProperty(deepExport=true, prefix="thumbnail_")
protected TaskViewThumbnail mThumbnailView;
@ViewDebug.ExportedProperty(deepExport=true, prefix="header_")
- TaskViewHeader mHeaderView;
+ protected TaskViewHeader mHeaderView;
private View mActionButtonView;
private View mIncompatibleAppToastView;
private TaskViewCallbacks mCb;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index 0777163..dc666e9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -91,6 +91,9 @@
if (mColor != color || Float.compare(mDimAlpha, dimAlpha) != 0) {
mColor = color;
mDimAlpha = dimAlpha;
+ if (mShouldDarkenBackgroundColor) {
+ color = getSecondaryColor(color, false /* useLightOverlayColor */);
+ }
mBackgroundPaint.setColor(color);
ColorUtils.colorToHSL(color, mTmpHSL);
@@ -179,6 +182,10 @@
// Header dim, which is only used when task view hardware layers are not used
private Paint mDimLayerPaint = new Paint();
+ // Whether the background color should be darkened to differentiate from the primary color.
+ // Used in grid layout.
+ private boolean mShouldDarkenBackgroundColor = false;
+
private CountDownTimer mFocusTimerCountDown;
public TaskViewHeader(Context context) {
@@ -443,6 +450,13 @@
}
/**
+ * Sets whether the background color should be darkened to differentiate from the primary color.
+ */
+ public void setShouldDarkenBackgroundColor(boolean flag) {
+ mShouldDarkenBackgroundColor = flag;
+ }
+
+ /**
* Binds the bar view to the task.
*/
public void bindToTask(Task t, boolean touchExplorationEnabled, boolean disabledInSafeMode) {
@@ -557,7 +571,7 @@
* Mark this task view that the user does has not interacted with the stack after a certain
* time.
*/
- void setNoUserInteractionState() {
+ public void setNoUserInteractionState() {
mDismissButton.setVisibility(View.VISIBLE);
mDismissButton.animate().cancel();
mDismissButton.setAlpha(1f);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskView.java
index a86abf6..8b4700c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskView.java
@@ -53,6 +53,7 @@
mThumbnailView.setOverlayHeaderOnThumbnailActionBar(false);
mThumbnailView.updateThumbnailMatrix();
mThumbnailView.setTranslationY(mHeaderHeight);
+ mHeaderView.setShouldDarkenBackgroundColor(true);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index 7825e9e..d3f997a 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -295,8 +295,10 @@
mAutomaticAvailable = context.getResources().getBoolean(
com.android.internal.R.bool.config_automatic_brightness_available);
- mPower = IPowerManager.Stub.asInterface(ServiceManager.getService("power"));
- mVrManager = IVrManager.Stub.asInterface(ServiceManager.getService("vrmanager"));
+ mPower = IPowerManager.Stub.asInterface(ServiceManager.getService(
+ Context.POWER_SERVICE));
+ mVrManager = IVrManager.Stub.asInterface(ServiceManager.getService(
+ Context.VR_SERVICE));
}
public void addStateChangedCallback(BrightnessStateChangeCallback cb) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 9245df0..5366da1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -25,7 +25,6 @@
import android.os.Message;
import android.support.annotation.VisibleForTesting;
import android.util.Pair;
-import android.view.KeyEvent;
import com.android.internal.os.SomeArgs;
import com.android.internal.statusbar.IStatusBar;
@@ -92,6 +91,8 @@
private final Object mLock = new Object();
private ArrayList<Callbacks> mCallbacks = new ArrayList<>();
private Handler mHandler = new H(Looper.getMainLooper());
+ private int mDisable1;
+ private int mDisable2;
/**
* These methods are called back on the main thread.
@@ -119,9 +120,9 @@
default void cancelPreloadRecentApps() { }
default void setWindowState(int window, int state) { }
default void showScreenPinningRequest(int taskId) { }
- default void appTransitionPending() { }
+ default void appTransitionPending(boolean forced) { }
default void appTransitionCancelled() { }
- default void appTransitionStarting(long startTime, long duration) { }
+ default void appTransitionStarting(long startTime, long duration, boolean forced) { }
default void appTransitionFinished() { }
default void showAssistDisclosure() { }
default void startAssist(Bundle args) { }
@@ -141,6 +142,7 @@
public void addCallbacks(Callbacks callbacks) {
mCallbacks.add(callbacks);
+ callbacks.disable(mDisable1, mDisable2, false /* animate */);
}
public void removeCallbacks(Callbacks callbacks) {
@@ -164,6 +166,8 @@
public void disable(int state1, int state2) {
synchronized (mLock) {
+ mDisable1 = state1;
+ mDisable2 = state2;
mHandler.removeMessages(MSG_DISABLE);
mHandler.obtainMessage(MSG_DISABLE, state1, state2, null).sendToTarget();
}
@@ -315,9 +319,13 @@
}
public void appTransitionPending() {
+ appTransitionPending(false /* forced */);
+ }
+
+ public void appTransitionPending(boolean forced) {
synchronized (mLock) {
mHandler.removeMessages(MSG_APP_TRANSITION_PENDING);
- mHandler.sendEmptyMessage(MSG_APP_TRANSITION_PENDING);
+ mHandler.obtainMessage(MSG_APP_TRANSITION_PENDING, forced ? 1 : 0, 0).sendToTarget();
}
}
@@ -329,10 +337,14 @@
}
public void appTransitionStarting(long startTime, long duration) {
+ appTransitionStarting(startTime, duration, false /* forced */);
+ }
+
+ public void appTransitionStarting(long startTime, long duration, boolean forced) {
synchronized (mLock) {
mHandler.removeMessages(MSG_APP_TRANSITION_STARTING);
- mHandler.obtainMessage(MSG_APP_TRANSITION_STARTING, Pair.create(startTime, duration))
- .sendToTarget();
+ mHandler.obtainMessage(MSG_APP_TRANSITION_STARTING, forced ? 1 : 0, 0,
+ Pair.create(startTime, duration)).sendToTarget();
}
}
@@ -505,7 +517,7 @@
break;
case MSG_APP_TRANSITION_PENDING:
for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).appTransitionPending();
+ mCallbacks.get(i).appTransitionPending(msg.arg1 != 0);
}
break;
case MSG_APP_TRANSITION_CANCELLED:
@@ -516,7 +528,8 @@
case MSG_APP_TRANSITION_STARTING:
for (int i = 0; i < mCallbacks.size(); i++) {
Pair<Long, Long> data = (Pair<Long, Long>) msg.obj;
- mCallbacks.get(i).appTransitionStarting(data.first, data.second);
+ mCallbacks.get(i).appTransitionStarting(data.first, data.second,
+ msg.arg1 != 0);
}
break;
case MSG_APP_TRANSITION_FINISHED:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
index 66cc15d..7f28c4c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar;
import com.android.internal.util.Preconditions;
+import com.android.systemui.Dependency;
import com.android.systemui.statusbar.phone.StatusBarWindowManager;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.RemoteInputView;
@@ -39,8 +40,8 @@
private final ArrayList<Callback> mCallbacks = new ArrayList<>(3);
private final HeadsUpManager mHeadsUpManager;
- public RemoteInputController(StatusBarWindowManager sbwm, HeadsUpManager headsUpManager) {
- addCallback(sbwm);
+ public RemoteInputController(HeadsUpManager headsUpManager) {
+ addCallback(Dependency.get(StatusBarWindowManager.class));
mHeadsUpManager = headsUpManager;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 45eb5df..89041f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -43,6 +43,8 @@
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
import com.android.systemui.statusbar.policy.NetworkControllerImpl;
@@ -54,10 +56,9 @@
import java.util.List;
// Intimately tied to the design of res/layout/signal_cluster_view.xml
-public class SignalClusterView
- extends LinearLayout
- implements NetworkControllerImpl.SignalCallback,
- SecurityController.SecurityControllerCallback, Tunable {
+public class SignalClusterView extends LinearLayout implements NetworkControllerImpl.SignalCallback,
+ SecurityController.SecurityControllerCallback, Tunable,
+ DarkReceiver {
static final String TAG = "SignalClusterView";
static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -581,7 +582,8 @@
return colorAccent;
}
- public void setIconTint(int tint, float darkIntensity, Rect tintArea) {
+ @Override
+ public void onDarkChanged(Rect tintArea, float darkIntensity, int tint) {
boolean changed = tint != mIconTint || darkIntensity != mDarkIntensity
|| !mTintArea.equals(tintArea);
mIconTint = tint;
@@ -593,16 +595,16 @@
}
private void applyIconTint() {
- setTint(mVpn, StatusBarIconController.getTint(mTintArea, mVpn, mIconTint));
- setTint(mAirplane, StatusBarIconController.getTint(mTintArea, mAirplane, mIconTint));
+ setTint(mVpn, DarkIconDispatcher.getTint(mTintArea, mVpn, mIconTint));
+ setTint(mAirplane, DarkIconDispatcher.getTint(mTintArea, mAirplane, mIconTint));
applyDarkIntensity(
- StatusBarIconController.getDarkIntensity(mTintArea, mNoSims, mDarkIntensity),
+ DarkIconDispatcher.getDarkIntensity(mTintArea, mNoSims, mDarkIntensity),
mNoSims, mNoSimsDark);
applyDarkIntensity(
- StatusBarIconController.getDarkIntensity(mTintArea, mWifi, mDarkIntensity),
+ DarkIconDispatcher.getDarkIntensity(mTintArea, mWifi, mDarkIntensity),
mWifi, mWifiDark);
applyDarkIntensity(
- StatusBarIconController.getDarkIntensity(mTintArea, mEthernet, mDarkIntensity),
+ DarkIconDispatcher.getDarkIntensity(mTintArea, mEthernet, mDarkIntensity),
mEthernet, mEthernetDark);
for (int i = 0; i < mPhoneStates.size(); i++) {
mPhoneStates.get(i).setIconTint(mIconTint, mDarkIntensity, mTintArea);
@@ -740,10 +742,10 @@
public void setIconTint(int tint, float darkIntensity, Rect tintArea) {
applyDarkIntensity(
- StatusBarIconController.getDarkIntensity(tintArea, mMobile, darkIntensity),
+ DarkIconDispatcher.getDarkIntensity(tintArea, mMobile, darkIntensity),
mMobile, mMobileDark);
- setTint(mMobileType, StatusBarIconController.getTint(tintArea, mMobileType, tint));
- setTint(mMobileRoaming, StatusBarIconController.getTint(tintArea, mMobileRoaming,
+ setTint(mMobileType, DarkIconDispatcher.getTint(tintArea, mMobileType, tint));
+ setTint(mMobileRoaming, DarkIconDispatcher.getTint(tintArea, mMobileRoaming,
tint));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 4161389..f53dad5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -32,17 +32,19 @@
import android.view.ViewStub;
import android.view.WindowManager;
import android.widget.LinearLayout;
+
import com.android.systemui.BatteryMeterView;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SwipeHelper;
+import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
import com.android.systemui.statusbar.phone.NavigationBarView;
import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.phone.PhoneStatusBarView;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
@@ -75,7 +77,6 @@
createBatteryController();
mCarBatteryController.startListening();
- mConnectedDeviceSignalController.startListening();
}
@Override
@@ -87,32 +88,40 @@
}
@Override
- protected PhoneStatusBarView makeStatusBarView() {
- PhoneStatusBarView statusBarView = super.makeStatusBarView();
+ protected void makeStatusBarView() {
+ super.makeStatusBarView();
- mBatteryMeterView = ((BatteryMeterView) statusBarView.findViewById(R.id.battery));
+ FragmentHostManager manager = FragmentHostManager.get(mStatusBarWindow);
+ manager.addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
+ mBatteryMeterView = ((BatteryMeterView) fragment.getView().findViewById(
+ R.id.battery));
- // By default, the BatteryMeterView should not be visible. It will be toggled visible
- // when a device has connected by bluetooth.
- mBatteryMeterView.setVisibility(View.GONE);
+ // By default, the BatteryMeterView should not be visible. It will be toggled
+ // when a device has connected by bluetooth.
+ mBatteryMeterView.setVisibility(View.GONE);
- ViewStub stub = (ViewStub) statusBarView.findViewById(R.id.connected_device_signals_stub);
- View signalsView = stub.inflate();
+ ViewStub stub = (ViewStub) fragment.getView().findViewById(
+ R.id.connected_device_signals_stub);
+ View signalsView = stub.inflate();
- // When a ViewStub if inflated, it does not respect the margins on the inflated view.
- // As a result, manually add the ending margin.
- ((LinearLayout.LayoutParams) signalsView.getLayoutParams()).setMarginEnd(
- mContext.getResources().getDimensionPixelOffset(
- R.dimen.status_bar_connected_device_signal_margin_end));
+ // When a ViewStub if inflated, it does not respect the margins on the
+ // inflated view.
+ // As a result, manually add the ending margin.
+ ((LinearLayout.LayoutParams) signalsView.getLayoutParams()).setMarginEnd(
+ mContext.getResources().getDimensionPixelOffset(
+ R.dimen.status_bar_connected_device_signal_margin_end));
- mConnectedDeviceSignalController = new ConnectedDeviceSignalController(mContext,
- signalsView);
+ if (mConnectedDeviceSignalController != null) {
+ mConnectedDeviceSignalController.stopListening();
+ }
+ mConnectedDeviceSignalController = new ConnectedDeviceSignalController(mContext,
+ signalsView);
+ mConnectedDeviceSignalController.startListening();
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "makeStatusBarView(). mBatteryMeterView: " + mBatteryMeterView);
- }
-
- return statusBarView;
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "makeStatusBarView(). mBatteryMeterView: " + mBatteryMeterView);
+ }
+ });
}
private BatteryController createBatteryController() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
new file mode 100644
index 0000000..1f56c56
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static com.android.systemui.statusbar.phone.StatusBar.reinflateSignalCluster;
+
+import android.annotation.Nullable;
+import android.app.Fragment;
+import android.app.StatusBarManager;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.SignalClusterView;
+import com.android.systemui.statusbar.phone.StatusBarIconController.DarkIconManager;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher;
+import com.android.systemui.statusbar.policy.EncryptionHelper;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.NetworkController;
+
+/**
+ * Contains the collapsed status bar and handles hiding/showing based on disable flags
+ * and keyguard state. Also manages lifecycle to make sure the views it contains are being
+ * updated by the StatusBarIconController and DarkIconManager while it is attached.
+ */
+public class CollapsedStatusBarFragment extends Fragment implements CommandQueue.Callbacks {
+
+ public static final String TAG = "CollapsedStatusBarFragment";
+ private PhoneStatusBarView mStatusBar;
+ private KeyguardMonitor mKeyguardMonitor;
+ private NetworkController mNetworkController;
+ private LinearLayout mSystemIconArea;
+ private View mNotificationIconAreaInner;
+ private int mDisabled1;
+ private StatusBar mStatusBarComponent;
+ private DarkIconManager mDarkIconManager;
+ private SignalClusterView mSignalClusterView;
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
+ mNetworkController = Dependency.get(NetworkController.class);
+ mStatusBarComponent = SysUiServiceProvider.getComponent(getContext(), StatusBar.class);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.status_bar, container, false);
+ }
+
+ @Override
+ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ mStatusBar = (PhoneStatusBarView) view;
+ mDarkIconManager = new DarkIconManager((LinearLayout) view.findViewById(R.id.statusIcons));
+ Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager);
+ mSystemIconArea = (LinearLayout) mStatusBar.findViewById(R.id.system_icon_area);
+ mSignalClusterView = reinflateSignalCluster(mStatusBar);
+ Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mSignalClusterView);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ SysUiServiceProvider.getComponent(getContext(), CommandQueue.class).addCallbacks(this);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ SysUiServiceProvider.getComponent(getContext(), CommandQueue.class).removeCallbacks(this);
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(mSignalClusterView);
+ Dependency.get(StatusBarIconController.class).removeIconGroup(mDarkIconManager);
+ }
+
+ public void initNotificationIconArea(NotificationIconAreaController
+ notificationIconAreaController) {
+ ViewGroup notificationIconArea = (ViewGroup) mStatusBar
+ .findViewById(R.id.notification_icon_area);
+ mNotificationIconAreaInner =
+ notificationIconAreaController.getNotificationInnerAreaView();
+ if (mNotificationIconAreaInner.getParent() != null) {
+ ((ViewGroup) mNotificationIconAreaInner.getParent())
+ .removeView(mNotificationIconAreaInner);
+ }
+ notificationIconArea.addView(mNotificationIconAreaInner);
+ }
+
+ @Override
+ public void disable(int state1, int state2, boolean animate) {
+ state1 = adjustDisableFlags(state1);
+ final int old1 = mDisabled1;
+ final int diff1 = state1 ^ old1;
+ mDisabled1 = state1;
+ if ((diff1 & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
+ if ((state1 & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
+ hideSystemIconArea(animate);
+ } else {
+ showSystemIconArea(animate);
+ }
+ }
+ if ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
+ if ((state1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
+ hideNotificationIconArea(animate);
+ } else {
+ showNotificationIconArea(animate);
+ }
+ }
+ }
+
+ protected int adjustDisableFlags(int state) {
+ if (!mStatusBarComponent.isLaunchTransitionFadingAway()
+ && !mKeyguardMonitor.isKeyguardFadingAway()
+ && shouldHideNotificationIcons()) {
+ state |= StatusBarManager.DISABLE_NOTIFICATION_ICONS;
+ state |= StatusBarManager.DISABLE_SYSTEM_INFO;
+ }
+ if (mNetworkController != null && EncryptionHelper.IS_DATA_ENCRYPTED) {
+ if (mNetworkController.hasEmergencyCryptKeeperText()) {
+ state |= StatusBarManager.DISABLE_NOTIFICATION_ICONS;
+ }
+ if (!mNetworkController.isRadioOn()) {
+ state |= StatusBarManager.DISABLE_SYSTEM_INFO;
+ }
+ }
+ return state;
+ }
+
+ private boolean shouldHideNotificationIcons() {
+ return !mStatusBar.isClosed() && mStatusBarComponent.shouldHideNotificationIcons();
+ }
+
+ public void hideSystemIconArea(boolean animate) {
+ animateHide(mSystemIconArea, animate);
+ }
+
+ public void showSystemIconArea(boolean animate) {
+ animateShow(mSystemIconArea, animate);
+ }
+
+ public void hideNotificationIconArea(boolean animate) {
+ animateHide(mNotificationIconAreaInner, animate);
+ }
+
+ public void showNotificationIconArea(boolean animate) {
+ animateShow(mNotificationIconAreaInner, animate);
+ }
+
+ /**
+ * Hides a view.
+ */
+ private void animateHide(final View v, boolean animate) {
+ v.animate().cancel();
+ if (!animate) {
+ v.setAlpha(0f);
+ v.setVisibility(View.INVISIBLE);
+ return;
+ }
+ v.animate()
+ .alpha(0f)
+ .setDuration(160)
+ .setStartDelay(0)
+ .setInterpolator(Interpolators.ALPHA_OUT)
+ .withEndAction(() -> v.setVisibility(View.INVISIBLE));
+ }
+
+ /**
+ * Shows a view, and synchronizes the animation with Keyguard exit animations, if applicable.
+ */
+ private void animateShow(View v, boolean animate) {
+ v.animate().cancel();
+ v.setVisibility(View.VISIBLE);
+ if (!animate) {
+ v.setAlpha(1f);
+ return;
+ }
+ v.animate()
+ .alpha(1f)
+ .setDuration(320)
+ .setInterpolator(Interpolators.ALPHA_IN)
+ .setStartDelay(50)
+
+ // We need to clean up any pending end action from animateHide if we call
+ // both hide and show in the same frame before the animation actually gets started.
+ // cancel() doesn't really remove the end action.
+ .withEndAction(null);
+
+ // Synchronize the motion with the Keyguard fading if necessary.
+ if (mKeyguardMonitor.isKeyguardFadingAway()) {
+ v.animate()
+ .setDuration(mKeyguardMonitor.getKeyguardFadingAwayDuration())
+ .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
+ .setStartDelay(mKeyguardMonitor.getKeyguardFadingAwayDelay())
+ .start();
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.java
new file mode 100644
index 0000000..020dc25
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.content.Context;
+import android.content.res.Configuration;
+
+import com.android.systemui.ConfigurationChangedReceiver;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+
+import java.util.ArrayList;
+
+public class ConfigurationControllerImpl implements ConfigurationController,
+ ConfigurationChangedReceiver {
+
+ private final ArrayList<ConfigurationListener> mListeners = new ArrayList<>();
+ private int mDensity;
+ private float mFontScale;
+
+ public ConfigurationControllerImpl(Context context) {
+ Configuration currentConfig = context.getResources().getConfiguration();
+ mFontScale = currentConfig.fontScale;
+ mDensity = currentConfig.densityDpi;
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ mListeners.forEach(l -> l.onConfigChanged(newConfig));
+ final float fontScale = newConfig.fontScale;
+ final int density = newConfig.densityDpi;
+ if (density != mDensity || mFontScale != fontScale) {
+ mListeners.forEach(l -> l.onDensityOrFontScaleChanged());
+ mDensity = density;
+ mFontScale = fontScale;
+ }
+ }
+
+ @Override
+ public void addCallback(ConfigurationListener listener) {
+ mListeners.add(listener);
+ listener.onDensityOrFontScaleChanged();
+ }
+
+ @Override
+ public void removeCallback(ConfigurationListener listener) {
+ mListeners.remove(listener);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java
new file mode 100644
index 0000000..3f9ae80
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static com.android.systemui.statusbar.policy.DarkIconDispatcher.getTint;
+
+import android.animation.ArgbEvaluator;
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Rect;
+import android.util.ArrayMap;
+import android.widget.ImageView;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher;
+
+public class DarkIconDispatcherImpl implements DarkIconDispatcher {
+
+ private final LightBarTransitionsController mTransitionsController;
+ private final Rect mTintArea = new Rect();
+ private final ArrayMap<Object, DarkReceiver> mReceivers = new ArrayMap<>();
+
+ private int mIconTint = DEFAULT_ICON_TINT;
+ private float mDarkIntensity;
+ private int mDarkModeIconColorSingleTone;
+ private int mLightModeIconColorSingleTone;
+
+ public DarkIconDispatcherImpl(Context context) {
+ mDarkModeIconColorSingleTone = context.getColor(R.color.dark_mode_icon_color_single_tone);
+ mLightModeIconColorSingleTone = context.getColor(R.color.light_mode_icon_color_single_tone);
+
+ mTransitionsController = new LightBarTransitionsController(context,
+ this::setIconTintInternal);
+ }
+
+ public LightBarTransitionsController getTransitionsController() {
+ return mTransitionsController;
+ }
+
+ public void addDarkReceiver(DarkReceiver receiver) {
+ mReceivers.put(receiver, receiver);
+ receiver.onDarkChanged(mTintArea, mDarkIntensity, mIconTint);
+ }
+
+ public void addDarkReceiver(ImageView imageView) {
+ DarkReceiver receiver = (area, darkIntensity, tint) -> imageView.setImageTintList(
+ ColorStateList.valueOf(getTint(mTintArea, imageView, mIconTint)));
+ mReceivers.put(imageView, receiver);
+ receiver.onDarkChanged(mTintArea, mDarkIntensity, mIconTint);
+ }
+
+ public void removeDarkReceiver(DarkReceiver object) {
+ mReceivers.remove(object);
+ }
+
+ public void removeDarkReceiver(ImageView object) {
+ mReceivers.remove(object);
+ }
+
+ public void applyDark(ImageView object) {
+ mReceivers.get(object).onDarkChanged(mTintArea, mDarkIntensity, mIconTint);
+ }
+
+ /**
+ * Sets the dark area so {@link #setIconsDark} only affects the icons in the specified area.
+ *
+ * @param darkArea the area in which icons should change it's tint, in logical screen
+ * coordinates
+ */
+ public void setIconsDarkArea(Rect darkArea) {
+ if (darkArea == null && mTintArea.isEmpty()) {
+ return;
+ }
+ if (darkArea == null) {
+ mTintArea.setEmpty();
+ } else {
+ mTintArea.set(darkArea);
+ }
+ applyIconTint();
+ }
+
+ private void setIconTintInternal(float darkIntensity) {
+ mDarkIntensity = darkIntensity;
+ mIconTint = (int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
+ mLightModeIconColorSingleTone, mDarkModeIconColorSingleTone);
+ applyIconTint();
+ }
+
+ private void applyIconTint() {
+ for (int i = 0; i < mReceivers.size(); i++) {
+ mReceivers.valueAt(i).onDarkChanged(mTintArea, mDarkIntensity, mIconTint);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
index 0773108..2bb3cbc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
@@ -27,6 +27,7 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.LatencyTracker;
+import com.android.systemui.Dependency;
import com.android.systemui.keyguard.KeyguardViewMediator;
/**
@@ -101,7 +102,6 @@
private int mPendingAuthenticatedUserId = -1;
public FingerprintUnlockController(Context context,
- StatusBarWindowManager statusBarWindowManager,
DozeScrimController dozeScrimController,
KeyguardViewMediator keyguardViewMediator,
ScrimController scrimController,
@@ -111,7 +111,7 @@
mPowerManager = context.getSystemService(PowerManager.class);
mUpdateMonitor = KeyguardUpdateMonitor.getInstance(context);
mUpdateMonitor.registerCallback(this);
- mStatusBarWindowManager = statusBarWindowManager;
+ mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class);
mDozeScrimController = dozeScrimController;
mKeyguardViewMediator = keyguardViewMediator;
mScrimController = scrimController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
index 7c458898..9d699cf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -22,6 +22,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -36,7 +37,7 @@
private static final float NAV_BAR_INVERSION_SCRIM_ALPHA_THRESHOLD = 0.1f;
- private final StatusBarIconController mStatusBarIconController;
+ private final DarkIconDispatcher mStatusBarIconController;
private final BatteryController mBatteryController;
private FingerprintUnlockController mFingerprintUnlockController;
@@ -65,8 +66,8 @@
private final Rect mLastFullscreenBounds = new Rect();
private final Rect mLastDockedBounds = new Rect();
- public LightBarController(StatusBarIconController statusBarIconController) {
- mStatusBarIconController = statusBarIconController;
+ public LightBarController() {
+ mStatusBarIconController = Dependency.get(DarkIconDispatcher.class);
mBatteryController = Dependency.get(BatteryController.class);
mBatteryController.addCallback(this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
index 07f37ab..6bd959f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
@@ -17,13 +17,19 @@
package com.android.systemui.statusbar.phone;
import android.animation.ValueAnimator;
+import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.util.TimeUtils;
import com.android.systemui.Dumpable;
+import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
+import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.CommandQueue.Callbacks;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -31,13 +37,14 @@
/**
* Class to control all aspects about light bar changes.
*/
-public class LightBarTransitionsController implements Dumpable {
+public class LightBarTransitionsController implements Dumpable, Callbacks {
public static final long DEFAULT_TINT_ANIMATION_DURATION = 120;
private static final String EXTRA_DARK_INTENSITY = "dark_intensity";
private final Handler mHandler;
private final DarkIntensityApplier mApplier;
+ private final KeyguardMonitor mKeyguardMonitor;
private boolean mTransitionDeferring;
private long mTransitionDeferringStartTime;
@@ -56,9 +63,17 @@
}
};
- public LightBarTransitionsController(DarkIntensityApplier applier) {
+ public LightBarTransitionsController(Context context, DarkIntensityApplier applier) {
mApplier = applier;
mHandler = new Handler();
+ mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
+ SysUiServiceProvider.getComponent(context, CommandQueue.class)
+ .addCallbacks(this);
+ }
+
+ public void destroy(Context context) {
+ SysUiServiceProvider.getComponent(context, CommandQueue.class)
+ .removeCallbacks(this);
}
public void saveState(Bundle outState) {
@@ -71,10 +86,15 @@
setIconTintInternal(savedInstanceState.getFloat(EXTRA_DARK_INTENSITY, 0));
}
- public void appTransitionPending() {
+ @Override
+ public void appTransitionPending(boolean forced) {
+ if (mKeyguardMonitor.isKeyguardGoingAway() && !forced) {
+ return;
+ }
mTransitionPending = true;
}
+ @Override
public void appTransitionCancelled() {
if (mTransitionPending && mTintChangePending) {
mTintChangePending = false;
@@ -83,7 +103,11 @@
mTransitionPending = false;
}
- public void appTransitionStarting(long startTime, long duration) {
+ @Override
+ public void appTransitionStarting(long startTime, long duration, boolean forced) {
+ if (mKeyguardMonitor.isKeyguardGoingAway() && !forced) {
+ return;
+ }
if (mTransitionPending && mTintChangePending) {
mTintChangePending = false;
animateIconTint(mPendingDarkIntensity,
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 808cd21..99f8aaf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -118,7 +118,6 @@
private int mSystemUiVisibility;
private LightBarController mLightBarController;
- private boolean mKeyguardGoingAway;
public boolean mHomeBlockedThisTouch;
@@ -195,6 +194,7 @@
@Override
public void onDestroyView() {
super.onDestroyView();
+ mNavigationBarView.getLightTransitionsController().destroy(getContext());
getContext().unregisterReceiver(mBroadcastReceiver);
}
@@ -287,31 +287,6 @@
}
}
- @Override
- public void appTransitionPending() {
- mNavigationBarView.getLightTransitionsController().appTransitionPending();
- }
-
- @Override
- public void appTransitionCancelled() {
- mNavigationBarView.getLightTransitionsController().appTransitionCancelled();
- }
-
- @Override
- public void appTransitionStarting(long startTime, long duration) {
- if (mKeyguardGoingAway) return;
- doAppTransitionStarting(startTime, duration);
- }
-
- /**
- * Calls appTransitionStarting for the nav bar regardless of whether keyguard is going away.
- * public so StatusBar can force this when needed.
- */
- public void doAppTransitionStarting(long startTime, long duration) {
- mNavigationBarView.getLightTransitionsController().appTransitionStarting(startTime,
- duration);
- }
-
// Injected from StatusBar at creation.
public void setCurrentSysuiVisibility(int systemUiVisibility) {
mSystemUiVisibility = systemUiVisibility;
@@ -612,10 +587,6 @@
delay + StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE);
}
- public void setKeyguardGoingAway(boolean keyguardGoingAway) {
- mKeyguardGoingAway = keyguardGoingAway;
- }
-
public BarTransitions getBarTransitions() {
return mNavigationBarView.getBarTransitions();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
index 3be5e57..cb925d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
@@ -38,7 +38,8 @@
mView = view;
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
- mLightTransitionsController = new LightBarTransitionsController(this::applyDarkIntensity);
+ mLightTransitionsController = new LightBarTransitionsController(view.getContext(),
+ this::applyDarkIntensity);
}
public void init() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 0386398..6d7ab47 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -17,6 +17,8 @@
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.notification.NotificationUtils;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import java.util.ArrayList;
@@ -26,7 +28,7 @@
* A controller for the space in the status bar to the left of the system icons. This area is
* normally reserved for notifications.
*/
-public class NotificationIconAreaController {
+public class NotificationIconAreaController implements DarkReceiver {
private final NotificationColorUtil mNotificationColorUtil;
private int mIconSize;
@@ -64,11 +66,12 @@
mNotificationIcons = (NotificationIconContainer) mNotificationIconArea.findViewById(
R.id.notificationIcons);
- NotificationShelf shelf = mStatusBar.getNotificationShelf();
+ mNotificationScrollLayout = mStatusBar.getNotificationScrollLayout();
+ }
+
+ public void setupShelf(NotificationShelf shelf) {
mShelfIcons = shelf.getShelfIcons();
shelf.setCollapsedIcons(mNotificationIcons);
-
- mNotificationScrollLayout = mStatusBar.getNotificationScrollLayout();
}
public void onDensityOrFontScaleChanged(Context context) {
@@ -102,23 +105,18 @@
}
/**
- * See {@link StatusBarIconController#setIconsDarkArea}.
+ * See {@link com.android.systemui.statusbar.policy.DarkIconDispatcher#setIconsDarkArea}.
+ * Sets the color that should be used to tint any icons in the notification area.
*
* @param tintArea the area in which to tint the icons, specified in screen coordinates
+ * @param darkIntensity
*/
- public void setTintArea(Rect tintArea) {
+ public void onDarkChanged(Rect tintArea, float darkIntensity, int iconTint) {
if (tintArea == null) {
mTintArea.setEmpty();
} else {
mTintArea.set(tintArea);
}
- applyNotificationIconsTint();
- }
-
- /**
- * Sets the color that should be used to tint any icons in the notification area.
- */
- public void setIconTint(int iconTint) {
mIconTint = iconTint;
applyNotificationIconsTint();
}
@@ -231,7 +229,7 @@
boolean colorize = !isPreL || NotificationUtils.isGrayscale(v, mNotificationColorUtil);
if (colorize) {
v.setImageTintList(ColorStateList.valueOf(
- StatusBarIconController.getTint(mTintArea, v, mIconTint)));
+ DarkIconDispatcher.getTint(mTintArea, v, mIconTint)));
}
v.setIconTint(mIconTint);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index 87a3848..23d3816 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -166,6 +166,10 @@
if (DEBUG) LOG("onPanelPeeked");
}
+ public boolean isClosed() {
+ return mState == STATE_CLOSED;
+ }
+
public void onPanelCollapsed() {
if (DEBUG) LOG("onPanelCollapsed");
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 1044ecf..93f874d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -38,24 +38,35 @@
import com.android.internal.telephony.TelephonyIntents;
import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.qs.tiles.DndTile;
import com.android.systemui.qs.tiles.RotationLockTile;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.CommandQueue.Callbacks;
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.BluetoothController.Callback;
import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.CastController.CastDevice;
import com.android.systemui.statusbar.policy.DataSaverController;
+import com.android.systemui.statusbar.policy.DataSaverController.Listener;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
import com.android.systemui.statusbar.policy.HotspotController;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.RotationLockController;
+import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback;
import com.android.systemui.statusbar.policy.UserInfoController;
+import com.android.systemui.statusbar.policy.ZenModeController;
/**
* This class contains all of the policy about which icons are installed in the status
* bar at boot time. It goes through the normal API for icons, even though it probably
* strictly doesn't need to.
*/
-public class PhoneStatusBarPolicy implements Callback, RotationLockController.RotationLockControllerCallback, DataSaverController.Listener {
+public class PhoneStatusBarPolicy implements Callback, Callbacks,
+ RotationLockControllerCallback, Listener,
+ ZenModeController.Callback, DeviceProvisionedListener, KeyguardMonitor.Callback {
private static final String TAG = "PhoneStatusBarPolicy";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -82,7 +93,9 @@
private final StatusBarIconController mIconController;
private final RotationLockController mRotationLockController;
private final DataSaverController mDataSaver;
- private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+ private final ZenModeController mZenController;
+ private final DeviceProvisionedController mProvisionedController;
+ private final KeyguardMonitor mKeyguardMonitor;
// Assume it's all good unless we hear otherwise. We don't always seem
// to get broadcasts that it *is* there.
@@ -106,13 +119,15 @@
mCast = Dependency.get(CastController.class);
mHotspot = Dependency.get(HotspotController.class);
mBluetooth = Dependency.get(BluetoothController.class);
- mBluetooth.addCallback(this);
mNextAlarm = Dependency.get(NextAlarmController.class);
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
mUserInfoController = Dependency.get(UserInfoController.class);
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
mRotationLockController = Dependency.get(RotationLockController.class);
mDataSaver = Dependency.get(DataSaverController.class);
+ mZenController = Dependency.get(ZenModeController.class);
+ mProvisionedController = Dependency.get(DeviceProvisionedController.class);
+ mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
mSlotCast = context.getString(com.android.internal.R.string.status_bar_cast);
mSlotHotspot = context.getString(com.android.internal.R.string.status_bar_hotspot);
@@ -127,7 +142,6 @@
mSlotHeadset = context.getString(com.android.internal.R.string.status_bar_headset);
mSlotDataSaver = context.getString(com.android.internal.R.string.status_bar_data_saver);
- mRotationLockController.addCallback(this);
// listen for broadcasts
IntentFilter filter = new IntentFilter();
@@ -158,7 +172,6 @@
// Alarm clock
mIconController.setIcon(mSlotAlarmClock, R.drawable.stat_sys_alarm, null);
mIconController.setIconVisibility(mSlotAlarmClock, false);
- mNextAlarm.addCallback(mNextAlarmCallback);
// zen
mIconController.setIcon(mSlotZen, R.drawable.stat_sys_zen_important, null);
@@ -172,13 +185,11 @@
// cast
mIconController.setIcon(mSlotCast, R.drawable.stat_sys_cast, null);
mIconController.setIconVisibility(mSlotCast, false);
- mCast.addCallback(mCastCallback);
// hotspot
mIconController.setIcon(mSlotHotspot, R.drawable.stat_sys_hotspot,
mContext.getString(R.string.accessibility_status_bar_hotspot));
mIconController.setIconVisibility(mSlotHotspot, mHotspot.isHotspotEnabled());
- mHotspot.addCallback(mHotspotCallback);
// managed profile
mIconController.setIcon(mSlotManagedProfile, R.drawable.stat_sys_managed_profile_status,
@@ -189,15 +200,36 @@
mIconController.setIcon(mSlotDataSaver, R.drawable.stat_sys_data_saver,
context.getString(R.string.accessibility_data_saver_on));
mIconController.setIconVisibility(mSlotDataSaver, false);
+
+ mRotationLockController.addCallback(this);
+ mBluetooth.addCallback(this);
+ mProvisionedController.addCallback(this);
+ mZenController.addCallback(this);
+ mCast.addCallback(mCastCallback);
+ mHotspot.addCallback(mHotspotCallback);
+ mNextAlarm.addCallback(mNextAlarmCallback);
mDataSaver.addCallback(this);
+ mKeyguardMonitor.addCallback(this);
+
+ SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallbacks(this);
}
- public void setStatusBarKeyguardViewManager(
- StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
- mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
+ public void destroy() {
+ mRotationLockController.removeCallback(this);
+ mBluetooth.removeCallback(this);
+ mProvisionedController.removeCallback(this);
+ mZenController.removeCallback(this);
+ mCast.removeCallback(mCastCallback);
+ mHotspot.removeCallback(mHotspotCallback);
+ mNextAlarm.removeCallback(mNextAlarmCallback);
+ mDataSaver.removeCallback(this);
+ mKeyguardMonitor.removeCallback(this);
+ SysUiServiceProvider.getComponent(mContext, CommandQueue.class).removeCallbacks(this);
+ mContext.unregisterReceiver(mIntentReceiver);
}
- public void setZenMode(int zen) {
+ @Override
+ public void onZenChanged(int zen) {
mZen = zen;
updateVolumeZen();
}
@@ -394,7 +426,7 @@
if (DEBUG) Log.v(TAG, "updateManagedProfile: mManagedProfileFocused: "
+ mManagedProfileFocused);
final boolean showIcon;
- if (mManagedProfileFocused && !mStatusBarKeyguardViewManager.isShowing()) {
+ if (mManagedProfileFocused && !mKeyguardMonitor.isShowing()) {
showIcon = true;
mIconController.setIcon(mSlotManagedProfile,
R.drawable.stat_sys_managed_profile_status,
@@ -471,15 +503,20 @@
}
};
- public void appTransitionStarting(long startTime, long duration) {
+ @Override
+ public void appTransitionStarting(long startTime, long duration, boolean forced) {
updateManagedProfile();
}
- public void notifyKeyguardShowingChanged() {
+ @Override
+ public void onKeyguardShowingChanged() {
updateManagedProfile();
}
- public void setCurrentUserSetup(boolean userSetup) {
+ @Override
+ public void onUserSetupChanged() {
+ boolean userSetup = mProvisionedController.isUserSetup(
+ mProvisionedController.getCurrentUser());
if (mCurrentUserSetup == userSetup) return;
mCurrentUserSetup = userSetup;
updateAlarm();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 7e088124..b52c26f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -24,9 +24,13 @@
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
+import com.android.systemui.BatteryMeterView;
import com.android.systemui.DejankUtils;
+import com.android.systemui.Dependency;
import com.android.systemui.EventLogTags;
import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
public class PhoneStatusBarView extends PanelBar {
private static final String TAG = "PhoneStatusBarView";
@@ -48,6 +52,7 @@
}
}
};
+ private DarkReceiver mBattery;
public PhoneStatusBarView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -70,6 +75,20 @@
@Override
public void onFinishInflate() {
mBarTransitions.init();
+ mBattery = (DarkReceiver) findViewById(R.id.battery);
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ // Always have Battery meters in the status bar observe the dark/light modes.
+ Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mBattery);
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(mBattery);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
index 4307a2e..457ed6c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -178,7 +178,7 @@
SignalClusterView cluster = (SignalClusterView) findViewById(R.id.signal_cluster);
int colorForeground = Utils.getColorAttr(getContext(), android.R.attr.colorForeground);
float intensity = colorForeground == Color.WHITE ? 0 : 1;
- cluster.setIconTint(colorForeground, intensity, new Rect(0, 0, 0, 0));
+ cluster.onDarkChanged(new Rect(0, 0, 0, 0), intensity, colorForeground);
BatteryMeterView battery = (BatteryMeterView) findViewById(R.id.battery);
int colorSecondary = Utils.getColorAttr(getContext(), android.R.attr.textColorSecondary);
battery.setRawColors(colorForeground, colorSecondary);
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 54c67d2..433dc3f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -173,13 +173,16 @@
import com.android.systemui.statusbar.SignalClusterView;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.phone.StatusBarIconController.IconManager;
import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
-import com.android.systemui.statusbar.policy.EncryptionHelper;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
@@ -279,6 +282,9 @@
protected static final boolean ENABLE_HEADS_UP = true;
protected static final String SETTING_HEADS_UP_TICKER = "ticker_gets_heads_up";
+ // Must match constant in Settings. Used to highlight preferences when linking to Settings.
+ private static final String EXTRA_FRAGMENT_ARG_KEY = ":settings:fragment_args_key";
+
private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
// Should match the values in PhoneWindowManager
@@ -501,9 +507,6 @@
}
updateQsExpansionEnabled();
}
- if (mIconPolicy != null) {
- mIconPolicy.setCurrentUserSetup(mUserSetup);
- }
}
};
@@ -709,6 +712,8 @@
private BatteryController mBatteryController;
private LogMaker mStatusBarStateLog;
private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
+ private NotificationIconAreaController mNotificationIconAreaController;
+ private ConfigurationListener mDensityChangeListener;
private void recycleAllVisibilityObjects(ArraySet<NotificationVisibility> array) {
final int N = array.size();
@@ -806,8 +811,6 @@
final Configuration currentConfig = mContext.getResources().getConfiguration();
mLocale = currentConfig.locale;
mLayoutDirection = TextUtils.getLayoutDirectionFromLocale(mLocale);
- mFontScale = currentConfig.fontScale;
- mDensity = currentConfig.densityDpi;
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
@@ -844,7 +847,7 @@
int N = iconSlots.size();
int viewIndex = 0;
for (int i=0; i < N; i++) {
- setIcon(iconSlots.get(i), icons.get(i));
+ mCommandQueue.setIcon(iconSlots.get(i), icons.get(i));
}
// Set up the initial notification state.
@@ -891,7 +894,8 @@
null, null);
updateCurrentProfilesCache();
- IVrManager vrManager = IVrManager.Stub.asInterface(ServiceManager.getService("vrmanager"));
+ IVrManager vrManager = IVrManager.Stub.asInterface(ServiceManager.getService(
+ Context.VR_SERVICE));
try {
vrManager.registerListener(mVrStateCallbacks);
} catch (RemoteException e) {
@@ -910,7 +914,6 @@
// Lastly, call to the icon policy to install/update all the icons.
mIconPolicy = new PhoneStatusBarPolicy(mContext, mIconController);
- mIconPolicy.setCurrentUserSetup(mUserSetup);
mSettingsObserver.onChange(false); // set up
mHeadsUpObserver.onChange(true); // set up
@@ -934,18 +937,25 @@
mScreenPinningRequest = new ScreenPinningRequest(mContext);
mFalsingManager = FalsingManager.getInstance(mContext);
+
Dependency.get(ActivityStarterDelegate.class).setActivityStarterImpl(this);
+
+ mDensityChangeListener = new ConfigurationListener() {
+ @Override
+ public void onDensityOrFontScaleChanged() {
+ StatusBar.this.onDensityOrFontScaleChanged();
+ }
+ };
+ Dependency.get(ConfigurationController.class).addCallback(mDensityChangeListener);
}
protected void createIconController() {
- mIconController = new StatusBarIconController(
- mContext, mStatusBarView, mKeyguardStatusBar, this);
}
// ================================================================================
// Constructing the view
// ================================================================================
- protected PhoneStatusBarView makeStatusBarView() {
+ protected void makeStatusBarView() {
final Context context = mContext;
updateDisplaySize(); // populates mDisplayMetrics
updateResources();
@@ -954,14 +964,37 @@
mStatusBarWindow.setService(this);
mStatusBarWindow.setOnTouchListener(getStatusBarWindowTouchListener());
+ // TODO: Deal with the ugliness that comes from having some of the statusbar broken out
+ // into fragments, but the rest here, it leaves some awkward lifecycle and whatnot.
mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById(
R.id.notification_panel);
+ mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(
+ R.id.notification_stack_scroller);
mNotificationPanel.setStatusBar(this);
mNotificationPanel.setGroupManager(mGroupManager);
+ mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header);
- mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar);
- mStatusBarView.setBar(this);
- mStatusBarView.setPanel(mNotificationPanel);
+ mNotificationIconAreaController = SystemUIFactory.getInstance()
+ .createNotificationIconAreaController(context, this);
+ inflateShelf();
+ mNotificationIconAreaController.setupShelf(mNotificationShelf);
+ Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mNotificationIconAreaController);
+ FragmentHostManager.get(mStatusBarWindow)
+ .addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
+ CollapsedStatusBarFragment statusBarFragment = (CollapsedStatusBarFragment) fragment;
+ statusBarFragment.initNotificationIconArea(mNotificationIconAreaController);
+ mStatusBarView = (PhoneStatusBarView) fragment.getView();
+ mStatusBarView.setBar(this);
+ mStatusBarView.setPanel(mNotificationPanel);
+ mStatusBarView.setScrimController(mScrimController);
+ setAreThereNotifications();
+ }).getFragmentManager()
+ .beginTransaction()
+ .replace(R.id.status_bar_container, new CollapsedStatusBarFragment(), CollapsedStatusBarFragment.TAG)
+ .commit();
+ Dependency.get(StatusBarIconController.class).addIconGroup(
+ new IconManager((ViewGroup) mKeyguardStatusBar.findViewById(R.id.statusIcons)));
+ mIconController = Dependency.get(StatusBarIconController.class);
if (!ActivityManager.isHighEndGfx()) {
mStatusBarWindow.setBackground(null);
@@ -999,8 +1032,6 @@
// figure out which pixel-format to use for the status bar.
mPixelFormat = PixelFormat.OPAQUE;
- mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(
- R.id.notification_stack_scroller);
mStackScroller.setLongPressListener(getNotificationLongClicker());
mStackScroller.setStatusBar(this);
mStackScroller.setGroupManager(mGroupManager);
@@ -1008,7 +1039,6 @@
mGroupManager.setOnGroupChangeListener(mStackScroller);
mVisualStabilityManager.setVisibilityLocationProvider(mStackScroller);
- inflateShelf();
inflateEmptyShadeView();
inflateDismissView();
mExpandedContents = mStackScroller;
@@ -1021,7 +1051,6 @@
mLockscreenWallpaper = new LockscreenWallpaper(mContext, this, mHandler);
}
- mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header);
mKeyguardStatusView =
(KeyguardStatusView) mStatusBarWindow.findViewById(R.id.keyguard_status_view);
mKeyguardBottomArea =
@@ -1035,8 +1064,6 @@
// set the initial view visibility
setAreThereNotifications();
- createIconController();
-
// TODO: Find better place for this callback.
mBatteryController.addCallback(new BatteryStateChangeCallback() {
@Override
@@ -1053,7 +1080,7 @@
}
});
- mLightBarController = new LightBarController(mIconController);
+ mLightBarController = new LightBarController();
if (mNavigationBar != null) {
mNavigationBar.setLightBarController(mLightBarController);
}
@@ -1077,7 +1104,6 @@
}
mHeadsUpManager.addListener(mScrimController);
mStackScroller.setScrimController(mScrimController);
- mStatusBarView.setScrimController(mScrimController);
mDozeScrimController = new DozeScrimController(mScrimController, context, mStackScroller,
mNotificationPanel);
@@ -1183,8 +1209,6 @@
// Private API call to make the shadows look better for Recents
ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f));
-
- return mStatusBarView;
}
protected void createNavigationBar() {
@@ -1258,12 +1282,13 @@
}
// end old BaseStatusBar.onDensityOrFontScaleChanged().
mScrimController.onDensityOrFontScaleChanged();
- mStatusBarView.onDensityOrFontScaleChanged();
+ // TODO: Remove this.
+ if (mStatusBarView != null) mStatusBarView.onDensityOrFontScaleChanged();
if (mBrightnessMirrorController != null) {
mBrightnessMirrorController.onDensityOrFontScaleChanged();
}
inflateSignalClusters();
- mIconController.onDensityOrFontScaleChanged();
+ mNotificationIconAreaController.onDensityOrFontScaleChanged(mContext);
inflateDismissView();
updateClearAll();
inflateEmptyShadeView();
@@ -1279,12 +1304,11 @@
}
private void inflateSignalClusters() {
- SignalClusterView signalClusterView = reinflateSignalCluster(mStatusBarView);
- mIconController.setSignalCluster(signalClusterView);
reinflateSignalCluster(mKeyguardStatusBar);
}
- private SignalClusterView reinflateSignalCluster(View view) {
+ public static SignalClusterView reinflateSignalCluster(View view) {
+ Context context = view.getContext();
SignalClusterView signalCluster =
(SignalClusterView) view.findViewById(R.id.signal_cluster);
if (signalCluster != null) {
@@ -1293,12 +1317,12 @@
ViewGroup viewParent = (ViewGroup) parent;
int index = viewParent.indexOfChild(signalCluster);
viewParent.removeView(signalCluster);
- SignalClusterView newCluster = (SignalClusterView) LayoutInflater.from(mContext)
+ SignalClusterView newCluster = (SignalClusterView) LayoutInflater.from(context)
.inflate(R.layout.signal_cluster_view, viewParent, false);
ViewGroup.MarginLayoutParams layoutParams =
(ViewGroup.MarginLayoutParams) viewParent.getLayoutParams();
layoutParams.setMarginsRelative(
- mContext.getResources().getDimensionPixelSize(
+ context.getResources().getDimensionPixelSize(
R.dimen.signal_cluster_margin_start),
0, 0, 0);
newCluster.setLayoutParams(layoutParams);
@@ -1422,26 +1446,22 @@
updateNotifications();
}
// end old BaseStatusBar.setZenMode().
- if (mIconPolicy != null) {
- mIconPolicy.setZenMode(mode);
- }
}
protected void startKeyguard() {
Trace.beginSection("StatusBar#startKeyguard");
KeyguardViewMediator keyguardViewMediator = getComponent(KeyguardViewMediator.class);
mFingerprintUnlockController = new FingerprintUnlockController(mContext,
- mStatusBarWindowManager, mDozeScrimController, keyguardViewMediator,
+ mDozeScrimController, keyguardViewMediator,
mScrimController, this, UnlockMethodCache.getInstance(mContext));
mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
- getBouncerContainer(), mStatusBarWindowManager, mScrimController,
+ getBouncerContainer(), mScrimController,
mFingerprintUnlockController);
mKeyguardIndicationController.setStatusBarKeyguardViewManager(
mStatusBarKeyguardViewManager);
mKeyguardIndicationController.setUserInfoController(
Dependency.get(UserInfoController.class));
mFingerprintUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
- mIconPolicy.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
mRemoteInputController.addCallback(mStatusBarKeyguardViewManager);
mRemoteInputController.addCallback(new RemoteInputController.Callback() {
@@ -1522,16 +1542,6 @@
}
}
- @Override
- public void setIcon(String slot, StatusBarIcon icon) {
- mIconController.setIcon(slot, icon);
- }
-
- @Override
- public void removeIcon(String slot) {
- mIconController.removeIcon(slot);
- }
-
public UserHandle getCurrentUserHandle() {
return new UserHandle(mCurrentUserId);
}
@@ -1894,7 +1904,7 @@
updateQsExpansionEnabled();
// Let's also update the icons
- mIconController.updateNotificationIcons(mNotificationData);
+ mNotificationIconAreaController.updateNotificationIcons(mNotificationData);
}
/**
@@ -2075,24 +2085,26 @@
hasActiveNotifications() + " clearable=" + clearable);
}
- final View nlo = mStatusBarView.findViewById(R.id.notification_lights_out);
- final boolean showDot = hasActiveNotifications() && !areLightsOn();
- if (showDot != (nlo.getAlpha() == 1.0f)) {
- if (showDot) {
- nlo.setAlpha(0f);
- nlo.setVisibility(View.VISIBLE);
+ if (mStatusBarView != null) {
+ final View nlo = mStatusBarView.findViewById(R.id.notification_lights_out);
+ final boolean showDot = hasActiveNotifications() && !areLightsOn();
+ if (showDot != (nlo.getAlpha() == 1.0f)) {
+ if (showDot) {
+ nlo.setAlpha(0f);
+ nlo.setVisibility(View.VISIBLE);
+ }
+ nlo.animate()
+ .alpha(showDot ? 1 : 0)
+ .setDuration(showDot ? 750 : 250)
+ .setInterpolator(new AccelerateInterpolator(2.0f))
+ .setListener(showDot ? null : new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator _a) {
+ nlo.setVisibility(View.GONE);
+ }
+ })
+ .start();
}
- nlo.animate()
- .alpha(showDot?1:0)
- .setDuration(showDot?750:250)
- .setInterpolator(new AccelerateInterpolator(2.0f))
- .setListener(showDot ? null : new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator _a) {
- nlo.setVisibility(View.GONE);
- }
- })
- .start();
}
findAndUpdateMediaNotifications();
@@ -2416,26 +2428,6 @@
&& mFalsingManager.isReportingEnabled() ? View.VISIBLE : View.INVISIBLE);
}
- protected int adjustDisableFlags(int state) {
- if (!mLaunchTransitionFadingAway && !mKeyguardFadingAway && shouldHideNotificationIcons()) {
- state |= StatusBarManager.DISABLE_NOTIFICATION_ICONS;
- state |= StatusBarManager.DISABLE_SYSTEM_INFO;
- }
- if (mNetworkController != null && EncryptionHelper.IS_DATA_ENCRYPTED) {
- if (mNetworkController.hasEmergencyCryptKeeperText()) {
- state |= StatusBarManager.DISABLE_NOTIFICATION_ICONS;
- }
- if (!mNetworkController.isRadioOn()) {
- state |= StatusBarManager.DISABLE_SYSTEM_INFO;
- }
- }
- return state;
- }
-
- private boolean shouldHideNotificationIcons() {
- return mExpandedVisible && mNotificationPanel.shouldHideNotificationIcons();
- }
-
/**
* State is one or more of the DISABLE constants from StatusBarManager.
*/
@@ -2444,7 +2436,6 @@
animate &= mStatusBarWindowState != WINDOW_STATE_HIDDEN;
mDisabledUnmodified1 = state1;
mDisabledUnmodified2 = state2;
- state1 = adjustDisableFlags(state1);
final int old1 = mDisabled1;
final int diff1 = state1 ^ old1;
mDisabled1 = state1;
@@ -2486,28 +2477,13 @@
flagdbg.append(">");
Log.d(TAG, flagdbg.toString());
- if ((diff1 & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
- if ((state1 & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
- mIconController.hideSystemIconArea(animate);
- } else {
- mIconController.showSystemIconArea(animate);
- }
- }
-
- if ((diff1 & StatusBarManager.DISABLE_CLOCK) != 0) {
- boolean visible = (state1 & StatusBarManager.DISABLE_CLOCK) == 0;
- mIconController.setClockVisibilityByPolicy(visible);
- }
if ((diff1 & StatusBarManager.DISABLE_EXPAND) != 0) {
if ((state1 & StatusBarManager.DISABLE_EXPAND) != 0) {
animateCollapsePanels();
}
}
- if ((diff1 & (StatusBarManager.DISABLE_HOME
- | StatusBarManager.DISABLE_RECENT
- | StatusBarManager.DISABLE_BACK
- | StatusBarManager.DISABLE_SEARCH)) != 0) {
+ if ((diff1 & StatusBarManager.DISABLE_RECENT) != 0) {
if ((state1 & StatusBarManager.DISABLE_RECENT) != 0) {
// close recents if it's visible
mHandler.removeMessages(MSG_HIDE_RECENT_APPS);
@@ -2515,14 +2491,6 @@
}
}
- if ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
- if ((state1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
- mIconController.hideNotificationIconArea(animate);
- } else {
- mIconController.showNotificationIconArea(animate);
- }
- }
-
if ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) {
mDisableNotificationAlerts =
(state1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0;
@@ -2736,10 +2704,6 @@
mFalsingManager.onScreenOff();
}
- public NotificationShelf getNotificationShelf() {
- return mNotificationShelf;
- }
-
public NotificationStackScrollLayout getNotificationScrollLayout() {
return mStackScroller;
}
@@ -2753,6 +2717,14 @@
updateNotifications();
}
+ public boolean isLaunchTransitionFadingAway() {
+ return mLaunchTransitionFadingAway;
+ }
+
+ public boolean shouldHideNotificationIcons() {
+ return mNotificationPanel.shouldHideNotificationIcons();
+ }
+
/**
* All changes to the status bar and notifications funnel through here and are batched.
*/
@@ -3158,7 +3130,8 @@
void checkBarModes() {
if (mDemoMode) return;
- checkBarMode(mStatusBarMode, mStatusBarWindowState, getStatusBarTransitions());
+ if (mStatusBarView != null) checkBarMode(mStatusBarMode, mStatusBarWindowState,
+ getStatusBarTransitions());
if (mNavigationBar != null) mNavigationBar.checkNavBarModes();
mNoAnimationOnNextBarModeChange = false;
}
@@ -3179,7 +3152,9 @@
}
private void finishBarAnimations() {
- mStatusBarView.getBarTransitions().finishAnimations();
+ if (mStatusBarView != null) {
+ mStatusBarView.getBarTransitions().finishAnimations();
+ }
if (mNavigationBar != null) {
mNavigationBar.finishBarAnimations();
}
@@ -3359,8 +3334,6 @@
mNotificationData.dump(pw, " ");
}
- mIconController.dump(pw);
-
if (false) {
pw.println("see the logcat for a dump of the views we have created.");
// must happen on ui thread
@@ -3381,9 +3354,6 @@
pw.print(" status bar gestures: ");
mGestureRec.dump(fd, pw, args);
}
- if (mStatusBarWindowManager != null) {
- mStatusBarWindowManager.dump(fd, pw, args);
- }
if (mHeadsUpManager != null) {
mHeadsUpManager.dump(fd, pw, args);
@@ -3422,9 +3392,8 @@
private void addStatusBarWindow() {
makeStatusBarView();
- mStatusBarWindowManager = new StatusBarWindowManager(mContext);
- mRemoteInputController = new RemoteInputController(mStatusBarWindowManager,
- mHeadsUpManager);
+ mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class);
+ mRemoteInputController = new RemoteInputController(mHeadsUpManager);
mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
}
@@ -3617,15 +3586,6 @@
protected void onConfigurationChanged(Configuration newConfig) {
updateResources();
updateDisplaySize(); // populates mDisplayMetrics
- // Begin old BaseStatusBar.onConfigurationChanged
- final float fontScale = newConfig.fontScale;
- final int density = newConfig.densityDpi;
- if (density != mDensity || mFontScale != fontScale) {
- onDensityOrFontScaleChanged();
- mDensity = density;
- mFontScale = fontScale;
- }
- // End old BaseStatusBar.onConfigurationChanged
if (DEBUG) {
Log.v(TAG, "configuration changed: " + mContext.getResources().getConfiguration());
@@ -3946,17 +3906,12 @@
mContext.unregisterReceiver(mDemoReceiver);
mAssistManager.destroy();
- final SignalClusterView signalCluster =
- (SignalClusterView) mStatusBarView.findViewById(R.id.signal_cluster);
- final SignalClusterView signalClusterKeyguard =
- (SignalClusterView) mKeyguardStatusBar.findViewById(R.id.signal_cluster);
- final SignalClusterView signalClusterQs =
- (SignalClusterView) mHeader.findViewById(R.id.signal_cluster);
if (mQSPanel != null && mQSPanel.getHost() != null) {
mQSPanel.getHost().destroy();
}
Dependency.get(ActivityStarterDelegate.class).setActivityStarterImpl(null);
mDeviceProvisionedController.removeCallback(mUserSetupObserver);
+ Dependency.get(ConfigurationController.class).removeCallback(mDensityChangeListener);
}
private boolean mDemoModeAllowed;
@@ -3989,7 +3944,7 @@
mBatteryController.dispatchDemoCommand(command, args);
}
if (modeChange || command.equals(COMMAND_STATUS)) {
- mIconController.dispatchDemoCommand(command, args);
+ ((StatusBarIconControllerImpl) mIconController).dispatchDemoCommand(command, args);
}
if (mNetworkController != null && (modeChange || command.equals(COMMAND_NETWORK))) {
mNetworkController.dispatchDemoCommand(command, args);
@@ -4132,14 +4087,8 @@
onLaunchTransitionFadingEnded();
}
});
- mIconController.getTransitionsController().appTransitionStarting(
- SystemClock.uptimeMillis(),
- LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION);
- if (mNavigationBar != null) {
- mNavigationBar.doAppTransitionStarting(
- SystemClock.uptimeMillis(),
- LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION);
- }
+ mCommandQueue.appTransitionStarting(SystemClock.uptimeMillis(),
+ LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true);
}
};
if (mNotificationPanel.isLaunchTransitionRunning()) {
@@ -4264,11 +4213,8 @@
// Treat Keyguard exit animation as an app transition to achieve nice transition for status
// bar.
mKeyguardGoingAway = true;
- mIconController.getTransitionsController().appTransitionPending();
- if (mNavigationBar != null) {
- mNavigationBar.setKeyguardGoingAway(true);
- mNavigationBar.appTransitionPending();
- }
+ mKeyguardMonitor.notifyKeyguardGoingAway(true);
+ mCommandQueue.appTransitionPending(true);
}
/**
@@ -4283,16 +4229,14 @@
mKeyguardFadingAwayDelay = delay;
mKeyguardFadingAwayDuration = fadeoutDuration;
mWaitingForKeyguardExit = false;
- mIconController.getTransitionsController().appTransitionStarting(
- startTime + fadeoutDuration
+ mCommandQueue.appTransitionStarting(startTime + fadeoutDuration
- LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION,
- LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION);
+ LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true);
recomputeDisableFlags(fadeoutDuration > 0 /* animate */);
- if (mNavigationBar != null) {
- mNavigationBar.doAppTransitionStarting(
+ mCommandQueue.appTransitionStarting(
startTime - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION,
- LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION);
- }
+ LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true);
+ mKeyguardMonitor.notifyKeyguardFadingAway(delay, fadeoutDuration);
}
public boolean isKeyguardFadingAway() {
@@ -4305,9 +4249,7 @@
public void finishKeyguardFadingAway() {
mKeyguardFadingAway = false;
mKeyguardGoingAway = false;
- if (mNavigationBar != null) {
- mNavigationBar.setKeyguardGoingAway(false);
- }
+ mKeyguardMonitor.notifyKeyguardDoneFading();
}
public void stopWaitingForKeyguardExit() {
@@ -4357,7 +4299,6 @@
} else {
mScrimController.setKeyguardShowing(false);
}
- mIconPolicy.notifyKeyguardShowingChanged();
mNotificationPanel.setBarState(mState, mKeyguardFadingAway, goingToFullShade);
updateDozingState();
updatePublicMode();
@@ -4945,33 +4886,11 @@
}
@Override
- public void appTransitionPending() {
- // Use own timings when Keyguard is going away, see keyguardGoingAway and
- // setKeyguardFadingAway
- if (!mKeyguardFadingAway) {
- mIconController.getTransitionsController().appTransitionPending();
- }
- }
-
- @Override
public void appTransitionCancelled() {
- mIconController.getTransitionsController().appTransitionCancelled();
EventBus.getDefault().send(new AppTransitionFinishedEvent());
}
@Override
- public void appTransitionStarting(long startTime, long duration) {
- // Use own timings when Keyguard is going away, see keyguardGoingAway and
- // setKeyguardFadingAway.
- if (!mKeyguardGoingAway) {
- mIconController.getTransitionsController().appTransitionStarting(startTime, duration);
- }
- if (mIconPolicy != null) {
- mIconPolicy.appTransitionStarting(startTime, duration);
- }
- }
-
- @Override
public void appTransitionFinished() {
EventBus.getDefault().send(new AppTransitionFinishedEvent());
}
@@ -5180,7 +5099,6 @@
private boolean mVisibleToUser;
private Locale mLocale;
- private float mFontScale;
protected boolean mUseHeadsUp = false;
protected boolean mHeadsUpTicker = false;
@@ -5197,7 +5115,6 @@
private final SparseBooleanArray mUsersAllowingNotifications = new SparseBooleanArray();
private UserManager mUserManager;
- private int mDensity;
protected KeyguardManager mKeyguardManager;
private LockPatternUtils mLockPatternUtils;
@@ -5789,10 +5706,12 @@
}
// The (i) button in the guts that links to the system notification settings for that app
- private void startAppNotificationSettingsActivity(String packageName, final int appUid) {
+ private void startAppNotificationSettingsActivity(String packageName, final int appUid,
+ final String channelId) {
final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName);
intent.putExtra(Settings.EXTRA_APP_UID, appUid);
+ intent.putExtra(EXTRA_FRAGMENT_ARG_KEY, channelId);
startNotificationGutsIntent(intent, appUid);
}
@@ -5857,7 +5776,7 @@
int appUid) -> {
MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTE_INFO);
guts.resetFalsingCheck();
- startAppNotificationSettingsActivity(pkg, appUid);
+ startAppNotificationSettingsActivity(pkg, appUid, channel.getId());
};
final View.OnClickListener onDoneClick = (View v) -> {
// If the user has security enabled, show challenge if the setting is changed.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index 41f8a91..c339da7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -1,502 +1,48 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * 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
+ * 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
+ * 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.systemui.statusbar.phone;
-import android.animation.ArgbEvaluator;
import android.content.Context;
-import android.content.res.ColorStateList;
-import android.content.res.Resources;
-import android.graphics.Color;
-import android.graphics.Rect;
-import android.graphics.drawable.Icon;
-import android.os.Bundle;
-import android.os.UserHandle;
import android.text.TextUtils;
import android.util.ArraySet;
-import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
-import android.widget.TextView;
+
import com.android.internal.statusbar.StatusBarIcon;
-import com.android.systemui.BatteryMeterView;
import com.android.systemui.Dependency;
-import com.android.systemui.FontSizeUtils;
-import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.SystemUIFactory;
-import com.android.systemui.statusbar.NotificationData;
-import com.android.systemui.statusbar.NotificationShelf;
-import com.android.systemui.statusbar.SignalClusterView;
import com.android.systemui.statusbar.StatusBarIconView;
-import com.android.systemui.tuner.TunerService;
-import com.android.systemui.tuner.TunerService.Tunable;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher;
-import java.io.PrintWriter;
-import java.util.ArrayList;
+public interface StatusBarIconController {
-/**
- * Controls everything regarding the icons in the status bar and on Keyguard, including, but not
- * limited to: notification icons, signal cluster, additional status icons, and clock in the status
- * bar.
- */
-public class StatusBarIconController extends StatusBarIconList implements Tunable {
+ public void addIconGroup(IconManager iconManager);
+ public void removeIconGroup(IconManager iconManager);
+ public void setExternalIcon(String slot);
+ public void setIcon(String slot, int resourceId, CharSequence contentDescription);
+ public void setIcon(String slot, StatusBarIcon icon);
+ public void setIconVisibility(String slotTty, boolean b);
+ public void removeIcon(String slot);
public static final String ICON_BLACKLIST = "icon_blacklist";
- public static final int DEFAULT_ICON_TINT = Color.WHITE;
-
- private Context mContext;
- private StatusBar mStatusBar;
- private DemoStatusIcons mDemoStatusIcons;
-
- private LinearLayout mSystemIconArea;
- private LinearLayout mStatusIcons;
- private SignalClusterView mSignalCluster;
- private LinearLayout mStatusIconsKeyguard;
-
- private NotificationIconAreaController mNotificationIconAreaController;
- private View mNotificationIconAreaInner;
- private NotificationShelf mNotificationShelf;
-
- private BatteryMeterView mBatteryMeterView;
- private BatteryMeterView mBatteryMeterViewKeyguard;
- private TextView mClock;
-
- private int mIconSize;
- private int mIconHPadding;
-
- private int mIconTint = DEFAULT_ICON_TINT;
- private float mDarkIntensity;
- private final Rect mTintArea = new Rect();
- private static final Rect sTmpRect = new Rect();
- private static final int[] sTmpInt2 = new int[2];
-
- private int mDarkModeIconColorSingleTone;
- private int mLightModeIconColorSingleTone;
-
- private final LightBarTransitionsController mTransitionsController;
-
- private boolean mClockVisibleByPolicy = true;
- private boolean mClockVisibleByUser = true;
-
- private final ArraySet<String> mIconBlacklist = new ArraySet<>();
-
- public StatusBarIconController(Context context, View statusBar, View keyguardStatusBar,
- StatusBar phoneStatusBar) {
- super(context.getResources().getStringArray(
- com.android.internal.R.array.config_statusBarIcons));
- mContext = context;
- mStatusBar = phoneStatusBar;
- mSystemIconArea = (LinearLayout) statusBar.findViewById(R.id.system_icon_area);
- mStatusIcons = (LinearLayout) statusBar.findViewById(R.id.statusIcons);
- mSignalCluster = (SignalClusterView) statusBar.findViewById(R.id.signal_cluster);
-
- mNotificationShelf = phoneStatusBar.getNotificationShelf();
- mNotificationIconAreaController = SystemUIFactory.getInstance()
- .createNotificationIconAreaController(context, phoneStatusBar);
- mNotificationIconAreaInner =
- mNotificationIconAreaController.getNotificationInnerAreaView();
-
- ViewGroup notificationIconArea =
- (ViewGroup) statusBar.findViewById(R.id.notification_icon_area);
- notificationIconArea.addView(mNotificationIconAreaInner);
-
- mStatusIconsKeyguard = (LinearLayout) keyguardStatusBar.findViewById(R.id.statusIcons);
-
- mBatteryMeterView = (BatteryMeterView) statusBar.findViewById(R.id.battery);
- mBatteryMeterViewKeyguard = (BatteryMeterView) keyguardStatusBar.findViewById(R.id.battery);
- scaleBatteryMeterViews(context);
-
- mClock = (TextView) statusBar.findViewById(R.id.clock);
- mDarkModeIconColorSingleTone = context.getColor(R.color.dark_mode_icon_color_single_tone);
- mLightModeIconColorSingleTone = context.getColor(R.color.light_mode_icon_color_single_tone);
- loadDimens();
-
- Dependency.get(TunerService.class).addTunable(this, ICON_BLACKLIST);
-
- mTransitionsController = new LightBarTransitionsController(this::setIconTintInternal);
- }
-
- public void setSignalCluster(SignalClusterView signalCluster) {
- mSignalCluster = signalCluster;
- }
-
- public LightBarTransitionsController getTransitionsController() {
- return mTransitionsController;
- }
-
- /**
- * Looks up the scale factor for status bar icons and scales the battery view by that amount.
- */
- private void scaleBatteryMeterViews(Context context) {
- Resources res = context.getResources();
- TypedValue typedValue = new TypedValue();
-
- res.getValue(R.dimen.status_bar_icon_scale_factor, typedValue, true);
- float iconScaleFactor = typedValue.getFloat();
-
- int batteryHeight = res.getDimensionPixelSize(R.dimen.status_bar_battery_icon_height);
- int batteryWidth = res.getDimensionPixelSize(R.dimen.status_bar_battery_icon_width);
- int marginBottom = res.getDimensionPixelSize(R.dimen.battery_margin_bottom);
-
- LinearLayout.LayoutParams scaledLayoutParams = new LinearLayout.LayoutParams(
- (int) (batteryWidth * iconScaleFactor), (int) (batteryHeight * iconScaleFactor));
- scaledLayoutParams.setMarginsRelative(0, 0, 0, marginBottom);
-
- mBatteryMeterView.setLayoutParams(scaledLayoutParams);
- mBatteryMeterViewKeyguard.setLayoutParams(scaledLayoutParams);
- }
-
- @Override
- public void onTuningChanged(String key, String newValue) {
- if (!ICON_BLACKLIST.equals(key)) {
- return;
- }
- mIconBlacklist.clear();
- mIconBlacklist.addAll(getIconBlacklist(newValue));
- ArrayList<StatusBarIconView> views = new ArrayList<StatusBarIconView>();
- // Get all the current views.
- for (int i = 0; i < mStatusIcons.getChildCount(); i++) {
- views.add((StatusBarIconView) mStatusIcons.getChildAt(i));
- }
- // Remove all the icons.
- for (int i = views.size() - 1; i >= 0; i--) {
- removeIcon(views.get(i).getSlot());
- }
- // Add them all back
- for (int i = 0; i < views.size(); i++) {
- setIcon(views.get(i).getSlot(), views.get(i).getStatusBarIcon());
- }
-
- setClockVisibleByUser(!StatusBarIconController.getIconBlacklist(newValue)
- .contains("clock"));
- updateClockVisibility();
- }
- private void loadDimens() {
- mIconSize = mContext.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_icon_size);
- mIconHPadding = mContext.getResources().getDimensionPixelSize(
- R.dimen.status_bar_icon_padding);
- }
-
- private void addSystemIcon(int index, StatusBarIcon icon) {
- String slot = getSlot(index);
- int viewIndex = getViewIndex(index);
- boolean blocked = mIconBlacklist.contains(slot);
- StatusBarIconView view = new StatusBarIconView(mContext, slot, null, blocked);
- view.set(icon);
-
- LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize);
- lp.setMargins(mIconHPadding, 0, mIconHPadding, 0);
- mStatusIcons.addView(view, viewIndex, lp);
-
- view = new StatusBarIconView(mContext, slot, null, blocked);
- view.set(icon);
- mStatusIconsKeyguard.addView(view, viewIndex, new LinearLayout.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize));
- applyIconTint();
- }
-
- public void setIcon(String slot, int resourceId, CharSequence contentDescription) {
- int index = getSlotIndex(slot);
- StatusBarIcon icon = getIcon(index);
- if (icon == null) {
- icon = new StatusBarIcon(UserHandle.SYSTEM, mContext.getPackageName(),
- Icon.createWithResource(mContext, resourceId), 0, 0, contentDescription);
- setIcon(slot, icon);
- } else {
- icon.icon = Icon.createWithResource(mContext, resourceId);
- icon.contentDescription = contentDescription;
- handleSet(index, icon);
- }
- }
-
- public void setExternalIcon(String slot) {
- int viewIndex = getViewIndex(getSlotIndex(slot));
- int height = mContext.getResources().getDimensionPixelSize(
- R.dimen.status_bar_icon_drawing_size);
- ImageView imageView = (ImageView) mStatusIcons.getChildAt(viewIndex);
- imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
- imageView.setAdjustViewBounds(true);
- setHeightAndCenter(imageView, height);
- imageView = (ImageView) mStatusIconsKeyguard.getChildAt(viewIndex);
- imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
- imageView.setAdjustViewBounds(true);
- setHeightAndCenter(imageView, height);
- }
-
- private void setHeightAndCenter(ImageView imageView, int height) {
- ViewGroup.LayoutParams params = imageView.getLayoutParams();
- params.height = height;
- if (params instanceof LinearLayout.LayoutParams) {
- ((LinearLayout.LayoutParams) params).gravity = Gravity.CENTER_VERTICAL;
- }
- imageView.setLayoutParams(params);
- }
-
- public void setIcon(String slot, StatusBarIcon icon) {
- setIcon(getSlotIndex(slot), icon);
- }
-
- public void removeIcon(String slot) {
- int index = getSlotIndex(slot);
- removeIcon(index);
- }
-
- public void setIconVisibility(String slot, boolean visibility) {
- int index = getSlotIndex(slot);
- StatusBarIcon icon = getIcon(index);
- if (icon == null || icon.visible == visibility) {
- return;
- }
- icon.visible = visibility;
- handleSet(index, icon);
- }
-
- @Override
- public void removeIcon(int index) {
- if (getIcon(index) == null) {
- return;
- }
- super.removeIcon(index);
- int viewIndex = getViewIndex(index);
- mStatusIcons.removeViewAt(viewIndex);
- mStatusIconsKeyguard.removeViewAt(viewIndex);
- }
-
- @Override
- public void setIcon(int index, StatusBarIcon icon) {
- if (icon == null) {
- removeIcon(index);
- return;
- }
- boolean isNew = getIcon(index) == null;
- super.setIcon(index, icon);
- if (isNew) {
- addSystemIcon(index, icon);
- } else {
- handleSet(index, icon);
- }
- }
-
- private void handleSet(int index, StatusBarIcon icon) {
- int viewIndex = getViewIndex(index);
- StatusBarIconView view = (StatusBarIconView) mStatusIcons.getChildAt(viewIndex);
- view.set(icon);
- view = (StatusBarIconView) mStatusIconsKeyguard.getChildAt(viewIndex);
- view.set(icon);
- applyIconTint();
- }
-
- public void updateNotificationIcons(NotificationData notificationData) {
- mNotificationIconAreaController.updateNotificationIcons(notificationData);
- }
-
- public void hideSystemIconArea(boolean animate) {
- animateHide(mSystemIconArea, animate);
- }
-
- public void showSystemIconArea(boolean animate) {
- animateShow(mSystemIconArea, animate);
- }
-
- public void hideNotificationIconArea(boolean animate) {
- animateHide(mNotificationIconAreaInner, animate);
- }
-
- public void showNotificationIconArea(boolean animate) {
- animateShow(mNotificationIconAreaInner, animate);
- }
-
- public void setClockVisibleByUser(boolean visible) {
- mClockVisibleByUser = visible;
- updateClockVisibility();
- }
-
- public void setClockVisibilityByPolicy(boolean visible) {
- mClockVisibleByPolicy = visible;
- updateClockVisibility();
- }
-
- private void updateClockVisibility() {
- int visibility = (mClockVisibleByPolicy && mClockVisibleByUser)
- ? View.VISIBLE : View.GONE;
- mClock.setVisibility(visibility);
- }
-
- public void dump(PrintWriter pw) {
- int N = mStatusIcons.getChildCount();
- pw.println(" icon views: " + N);
- for (int i=0; i<N; i++) {
- StatusBarIconView ic = (StatusBarIconView) mStatusIcons.getChildAt(i);
- pw.println(" [" + i + "] icon=" + ic);
- }
- super.dump(pw);
- }
-
- public void dispatchDemoCommand(String command, Bundle args) {
- if (mDemoStatusIcons == null) {
- mDemoStatusIcons = new DemoStatusIcons(mStatusIcons, mIconSize);
- }
- mDemoStatusIcons.dispatchDemoCommand(command, args);
- }
-
- /**
- * Hides a view.
- */
- private void animateHide(final View v, boolean animate) {
- v.animate().cancel();
- if (!animate) {
- v.setAlpha(0f);
- v.setVisibility(View.INVISIBLE);
- return;
- }
- v.animate()
- .alpha(0f)
- .setDuration(160)
- .setStartDelay(0)
- .setInterpolator(Interpolators.ALPHA_OUT)
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- v.setVisibility(View.INVISIBLE);
- }
- });
- }
-
- /**
- * Shows a view, and synchronizes the animation with Keyguard exit animations, if applicable.
- */
- private void animateShow(View v, boolean animate) {
- v.animate().cancel();
- v.setVisibility(View.VISIBLE);
- if (!animate) {
- v.setAlpha(1f);
- return;
- }
- v.animate()
- .alpha(1f)
- .setDuration(320)
- .setInterpolator(Interpolators.ALPHA_IN)
- .setStartDelay(50)
-
- // We need to clean up any pending end action from animateHide if we call
- // both hide and show in the same frame before the animation actually gets started.
- // cancel() doesn't really remove the end action.
- .withEndAction(null);
-
- // Synchronize the motion with the Keyguard fading if necessary.
- if (mStatusBar.isKeyguardFadingAway()) {
- v.animate()
- .setDuration(mStatusBar.getKeyguardFadingAwayDuration())
- .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
- .setStartDelay(mStatusBar.getKeyguardFadingAwayDelay())
- .start();
- }
- }
-
- /**
- * Sets the dark area so {@link #setIconsDark} only affects the icons in the specified area.
- *
- * @param darkArea the area in which icons should change it's tint, in logical screen
- * coordinates
- */
- public void setIconsDarkArea(Rect darkArea) {
- if (darkArea == null && mTintArea.isEmpty()) {
- return;
- }
- if (darkArea == null) {
- mTintArea.setEmpty();
- } else {
- mTintArea.set(darkArea);
- }
- applyIconTint();
- mNotificationIconAreaController.setTintArea(darkArea);
- }
-
- private void setIconTintInternal(float darkIntensity) {
- mDarkIntensity = darkIntensity;
- mIconTint = (int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
- mLightModeIconColorSingleTone, mDarkModeIconColorSingleTone);
- mNotificationIconAreaController.setIconTint(mIconTint);
- applyIconTint();
- }
-
- /**
- * @return the tint to apply to {@param view} depending on the desired tint {@param color} and
- * the screen {@param tintArea} in which to apply that tint
- */
- public static int getTint(Rect tintArea, View view, int color) {
- if (isInArea(tintArea, view)) {
- return color;
- } else {
- return DEFAULT_ICON_TINT;
- }
- }
-
- /**
- * @return the dark intensity to apply to {@param view} depending on the desired dark
- * {@param intensity} and the screen {@param tintArea} in which to apply that intensity
- */
- public static float getDarkIntensity(Rect tintArea, View view, float intensity) {
- if (isInArea(tintArea, view)) {
- return intensity;
- } else {
- return 0f;
- }
- }
-
- /**
- * @return true if more than half of the {@param view} area are in {@param area}, false
- * otherwise
- */
- private static boolean isInArea(Rect area, View view) {
- if (area.isEmpty()) {
- return true;
- }
- sTmpRect.set(area);
- view.getLocationOnScreen(sTmpInt2);
- int left = sTmpInt2[0];
-
- int intersectStart = Math.max(left, area.left);
- int intersectEnd = Math.min(left + view.getWidth(), area.right);
- int intersectAmount = Math.max(0, intersectEnd - intersectStart);
-
- boolean coversFullStatusBar = area.top <= 0;
- boolean majorityOfWidth = 2 * intersectAmount > view.getWidth();
- return majorityOfWidth && coversFullStatusBar;
- }
-
- private void applyIconTint() {
- for (int i = 0; i < mStatusIcons.getChildCount(); i++) {
- StatusBarIconView v = (StatusBarIconView) mStatusIcons.getChildAt(i);
- v.setImageTintList(ColorStateList.valueOf(getTint(mTintArea, v, mIconTint)));
- }
- mSignalCluster.setIconTint(mIconTint, mDarkIntensity, mTintArea);
- mBatteryMeterView.setDarkIntensity(
- isInArea(mTintArea, mBatteryMeterView) ? mDarkIntensity : 0);
- mClock.setTextColor(getTint(mTintArea, mClock, mIconTint));
- }
public static ArraySet<String> getIconBlacklist(String blackListStr) {
- ArraySet<String> ret = new ArraySet<String>();
+ ArraySet<String> ret = new ArraySet<>();
if (blackListStr == null) {
blackListStr = "rotate,headset";
}
@@ -509,34 +55,110 @@
return ret;
}
- public void onDensityOrFontScaleChanged() {
- loadDimens();
- mNotificationIconAreaController.onDensityOrFontScaleChanged(mContext);
- updateClock();
- for (int i = 0; i < mStatusIcons.getChildCount(); i++) {
- View child = mStatusIcons.getChildAt(i);
+
+ /**
+ * Version of ViewGroup that observers state from the DarkIconDispatcher.
+ */
+ public static class DarkIconManager extends IconManager {
+ private final DarkIconDispatcher mDarkIconDispatcher;
+ private int mIconHPadding;
+
+ public DarkIconManager(LinearLayout linearLayout) {
+ super(linearLayout);
+ mIconHPadding = mContext.getResources().getDimensionPixelSize(
+ R.dimen.status_bar_icon_padding);
+ mDarkIconDispatcher = Dependency.get(DarkIconDispatcher.class);
+ }
+
+ @Override
+ protected void onIconAdded(int index, String slot, boolean blocked, StatusBarIcon icon) {
+ StatusBarIconView view = new StatusBarIconView(mContext, slot, null, blocked);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize);
lp.setMargins(mIconHPadding, 0, mIconHPadding, 0);
- child.setLayoutParams(lp);
+ mGroup.addView(view, index, lp);
+ mDarkIconDispatcher.addDarkReceiver(view);
}
- for (int i = 0; i < mStatusIconsKeyguard.getChildCount(); i++) {
- View child = mStatusIconsKeyguard.getChildAt(i);
- LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize);
- child.setLayoutParams(lp);
+
+ @Override
+ protected void destroy() {
+ for (int i = 0; i < mGroup.getChildCount(); i++) {
+ mDarkIconDispatcher.removeDarkReceiver((ImageView) mGroup.getChildAt(i));
+ }
+ mGroup.removeAllViews();
}
- scaleBatteryMeterViews(mContext);
+
+ @Override
+ protected void onRemoveIcon(int viewIndex) {
+ mDarkIconDispatcher.removeDarkReceiver((ImageView) mGroup.getChildAt(viewIndex));
+ super.onRemoveIcon(viewIndex);
+ }
+
+ @Override
+ public void onSetIcon(int viewIndex, StatusBarIcon icon) {
+ super.onSetIcon(viewIndex, icon);
+ mDarkIconDispatcher.applyDark((ImageView) mGroup.getChildAt(viewIndex));
+ }
}
- private void updateClock() {
- FontSizeUtils.updateFontSize(mClock, R.dimen.status_bar_clock_size);
- mClock.setPaddingRelative(
- mContext.getResources().getDimensionPixelSize(
- R.dimen.status_bar_clock_starting_padding),
- 0,
- mContext.getResources().getDimensionPixelSize(
- R.dimen.status_bar_clock_end_padding),
- 0);
+ /**
+ * Turns info from StatusBarIconController into ImageViews in a ViewGroup.
+ */
+ public static class IconManager {
+ protected final ViewGroup mGroup;
+ protected final Context mContext;
+ protected final int mIconSize;
+
+ public IconManager(ViewGroup group) {
+ mGroup = group;
+ mContext = group.getContext();
+ mIconSize = mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.status_bar_icon_size);
+ }
+
+ protected void onIconAdded(int index, String slot, boolean blocked, StatusBarIcon icon) {
+ StatusBarIconView view = new StatusBarIconView(mContext, slot, null, blocked);
+ view.set(icon);
+ mGroup.addView(view, index, new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize));
+ }
+
+ protected void destroy() {
+ mGroup.removeAllViews();
+ }
+
+ protected void onIconExternal(int viewIndex, int height) {
+ ImageView imageView = (ImageView) mGroup.getChildAt(viewIndex);
+ imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
+ imageView.setAdjustViewBounds(true);
+ setHeightAndCenter(imageView, height);
+ }
+
+ protected void onDensityOrFontScaleChanged() {
+ for (int i = 0; i < mGroup.getChildCount(); i++) {
+ View child = mGroup.getChildAt(i);
+ LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize);
+ child.setLayoutParams(lp);
+ }
+ }
+
+ private void setHeightAndCenter(ImageView imageView, int height) {
+ ViewGroup.LayoutParams params = imageView.getLayoutParams();
+ params.height = height;
+ if (params instanceof LinearLayout.LayoutParams) {
+ ((LinearLayout.LayoutParams) params).gravity = Gravity.CENTER_VERTICAL;
+ }
+ imageView.setLayoutParams(params);
+ }
+
+ protected void onRemoveIcon(int viewIndex) {
+ mGroup.removeViewAt(viewIndex);
+ }
+
+ public void onSetIcon(int viewIndex, StatusBarIcon icon) {
+ StatusBarIconView view = (StatusBarIconView) mGroup.getChildAt(viewIndex);
+ view.set(icon);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
new file mode 100644
index 0000000..70b92ad
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.content.Context;
+import android.graphics.drawable.Icon;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.ArraySet;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+import com.android.internal.statusbar.StatusBarIcon;
+import com.android.systemui.Dependency;
+import com.android.systemui.Dumpable;
+import com.android.systemui.R;
+import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerService.Tunable;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * Receives the callbacks from CommandQueue related to icons and tracks the state of
+ * all the icons. Dispatches this state to any IconManagers that are currently
+ * registered with it.
+ */
+public class StatusBarIconControllerImpl extends StatusBarIconList implements Tunable,
+ ConfigurationListener, Dumpable, CommandQueue.Callbacks, StatusBarIconController {
+
+ private final DarkIconDispatcher mDarkIconDispatcher;
+
+ private Context mContext;
+ private DemoStatusIcons mDemoStatusIcons;
+
+ private final ArrayList<IconManager> mIconGroups = new ArrayList<>();
+
+ private final ArraySet<String> mIconBlacklist = new ArraySet<>();
+
+ public StatusBarIconControllerImpl(Context context) {
+ super(context.getResources().getStringArray(
+ com.android.internal.R.array.config_statusBarIcons));
+ Dependency.get(ConfigurationController.class).addCallback(this);
+ mDarkIconDispatcher = Dependency.get(DarkIconDispatcher.class);
+ mContext = context;
+
+ loadDimens();
+
+ SysUiServiceProvider.getComponent(context, CommandQueue.class)
+ .addCallbacks(this);
+ Dependency.get(TunerService.class).addTunable(this, ICON_BLACKLIST);
+ }
+
+ @Override
+ public void addIconGroup(IconManager group) {
+ mIconGroups.add(group);
+ for (int i = 0; i < mIcons.size(); i++) {
+ StatusBarIcon icon = mIcons.get(i);
+ if (icon != null) {
+ String slot = mSlots.get(i);
+ boolean blocked = mIconBlacklist.contains(slot);
+ group.onIconAdded(getViewIndex(getSlotIndex(slot)), slot, blocked, icon);
+ }
+ }
+ }
+
+ @Override
+ public void removeIconGroup(IconManager group) {
+ group.destroy();
+ mIconGroups.remove(group);
+ }
+
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ if (!ICON_BLACKLIST.equals(key)) {
+ return;
+ }
+ mIconBlacklist.clear();
+ mIconBlacklist.addAll(StatusBarIconController.getIconBlacklist(newValue));
+ ArrayList<StatusBarIcon> current = new ArrayList<>(mIcons);
+ ArrayList<String> currentSlots = new ArrayList<>(mSlots);
+ // Remove all the icons.
+ for (int i = current.size() - 1; i >= 0; i--) {
+ removeIcon(currentSlots.get(i));
+ }
+ // Add them all back
+ for (int i = 0; i < current.size(); i++) {
+ setIcon(currentSlots.get(i), current.get(i));
+ }
+ }
+
+ private void loadDimens() {
+ }
+
+ private void addSystemIcon(int index, StatusBarIcon icon) {
+ String slot = getSlot(index);
+ int viewIndex = getViewIndex(index);
+ boolean blocked = mIconBlacklist.contains(slot);
+
+ mIconGroups.forEach(l -> l.onIconAdded(viewIndex, slot, blocked, icon));
+ }
+
+ @Override
+ public void setIcon(String slot, int resourceId, CharSequence contentDescription) {
+ int index = getSlotIndex(slot);
+ StatusBarIcon icon = getIcon(index);
+ if (icon == null) {
+ icon = new StatusBarIcon(UserHandle.SYSTEM, mContext.getPackageName(),
+ Icon.createWithResource(mContext, resourceId), 0, 0, contentDescription);
+ setIcon(slot, icon);
+ } else {
+ icon.icon = Icon.createWithResource(mContext, resourceId);
+ icon.contentDescription = contentDescription;
+ handleSet(index, icon);
+ }
+ }
+
+ @Override
+ public void setExternalIcon(String slot) {
+ int viewIndex = getViewIndex(getSlotIndex(slot));
+ int height = mContext.getResources().getDimensionPixelSize(
+ R.dimen.status_bar_icon_drawing_size);
+ mIconGroups.forEach(l -> l.onIconExternal(viewIndex, height));
+ }
+
+ @Override
+ public void setIcon(String slot, StatusBarIcon icon) {
+ setIcon(getSlotIndex(slot), icon);
+ }
+
+ @Override
+ public void removeIcon(String slot) {
+ int index = getSlotIndex(slot);
+ removeIcon(index);
+ }
+
+ public void setIconVisibility(String slot, boolean visibility) {
+ int index = getSlotIndex(slot);
+ StatusBarIcon icon = getIcon(index);
+ if (icon == null || icon.visible == visibility) {
+ return;
+ }
+ icon.visible = visibility;
+ handleSet(index, icon);
+ }
+
+ @Override
+ public void removeIcon(int index) {
+ if (getIcon(index) == null) {
+ return;
+ }
+ super.removeIcon(index);
+ int viewIndex = getViewIndex(index);
+ mIconGroups.forEach(l -> l.onRemoveIcon(viewIndex));
+ }
+
+ @Override
+ public void setIcon(int index, StatusBarIcon icon) {
+ if (icon == null) {
+ removeIcon(index);
+ return;
+ }
+ boolean isNew = getIcon(index) == null;
+ super.setIcon(index, icon);
+ if (isNew) {
+ addSystemIcon(index, icon);
+ } else {
+ handleSet(index, icon);
+ }
+ }
+
+ private void handleSet(int index, StatusBarIcon icon) {
+ int viewIndex = getViewIndex(index);
+ mIconGroups.forEach(l -> l.onSetIcon(viewIndex, icon));
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ // TODO: Dump info about all icon groups?
+ ViewGroup statusIcons = mIconGroups.get(0).mGroup;
+ int N = statusIcons.getChildCount();
+ pw.println(" icon views: " + N);
+ for (int i = 0; i < N; i++) {
+ StatusBarIconView ic = (StatusBarIconView) statusIcons.getChildAt(i);
+ pw.println(" [" + i + "] icon=" + ic);
+ }
+ super.dump(pw);
+ }
+
+ public void dispatchDemoCommand(String command, Bundle args) {
+ if (mDemoStatusIcons == null) {
+ // TODO: Rework how we handle demo mode.
+ int iconSize = mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.status_bar_icon_size);
+ mDemoStatusIcons = new DemoStatusIcons((LinearLayout) mIconGroups.get(0).mGroup,
+ iconSize);
+ }
+ mDemoStatusIcons.dispatchDemoCommand(command, args);
+ }
+
+ @Override
+ public void onDensityOrFontScaleChanged() {
+ loadDimens();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
index 660672d..f600908 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
@@ -22,8 +22,8 @@
import java.util.ArrayList;
public class StatusBarIconList {
- private ArrayList<String> mSlots = new ArrayList<>();
- private ArrayList<StatusBarIcon> mIcons = new ArrayList<>();
+ protected ArrayList<String> mSlots = new ArrayList<>();
+ protected ArrayList<StatusBarIcon> mIcons = new ArrayList<>();
public StatusBarIconList(String[] slots) {
final int N = slots.length;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 8d5d890..2a69c1e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -32,6 +32,7 @@
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.DejankUtils;
import com.android.keyguard.LatencyTracker;
+import com.android.systemui.Dependency;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.statusbar.CommandQueue;
@@ -67,6 +68,7 @@
private static String TAG = "StatusBarKeyguardViewManager";
protected final Context mContext;
+ private final StatusBarWindowManager mStatusBarWindowManager;
protected LockPatternUtils mLockPatternUtils;
protected ViewMediatorCallback mViewMediatorCallback;
@@ -75,7 +77,6 @@
private FingerprintUnlockController mFingerprintUnlockController;
private ViewGroup mContainer;
- private StatusBarWindowManager mStatusBarWindowManager;
private boolean mDeviceInteractive = false;
private boolean mScreenTurnedOn;
@@ -101,16 +102,16 @@
mContext = context;
mViewMediatorCallback = callback;
mLockPatternUtils = lockPatternUtils;
+ mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class);
}
public void registerStatusBar(StatusBar statusBar,
- ViewGroup container, StatusBarWindowManager statusBarWindowManager,
+ ViewGroup container,
ScrimController scrimController,
FingerprintUnlockController fingerprintUnlockController,
DismissCallbackRegistry dismissCallbackRegistry) {
mStatusBar = statusBar;
mContainer = container;
- mStatusBarWindowManager = statusBarWindowManager;
mScrimController = scrimController;
mFingerprintUnlockController = fingerprintUnlockController;
mBouncer = SystemUIFactory.getInstance().createKeyguardBouncer(mContext,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index 16999b2..deb0070 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -32,6 +32,7 @@
import android.view.WindowManager;
import com.android.keyguard.R;
+import com.android.systemui.Dumpable;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
@@ -43,7 +44,7 @@
/**
* Encapsulates all logic for the status bar window state management.
*/
-public class StatusBarWindowManager implements RemoteInputController.Callback {
+public class StatusBarWindowManager implements RemoteInputController.Callback, Dumpable {
private static final String TAG = "StatusBarWindowManager";
@@ -59,6 +60,7 @@
private final boolean mKeyguardScreenRotation;
private final float mScreenBrightnessDoze;
private final State mCurrentState = new State();
+ private OtherwisedCollapsedListener mListener;
public StatusBarWindowManager(Context context) {
mContext = context;
@@ -154,6 +156,10 @@
private void applyHeight(State state) {
boolean expanded = isExpanded(state);
+ if (state.forcePluginOpen) {
+ mListener.setWouldOtherwiseCollapse(expanded);
+ expanded = true;
+ }
if (expanded) {
mLpChanged.height = ViewGroup.LayoutParams.MATCH_PARENT;
} else {
@@ -356,6 +362,15 @@
apply(mCurrentState);
}
+ public void setForcePluginOpen(boolean forcePluginOpen) {
+ mCurrentState.forcePluginOpen = forcePluginOpen;
+ apply(mCurrentState);
+ }
+
+ public void setStateListener(OtherwisedCollapsedListener listener) {
+ mListener = listener;
+ }
+
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("StatusBarWindowManager state:");
pw.println(mCurrentState);
@@ -388,6 +403,7 @@
int statusBarState;
boolean remoteInputActive;
+ boolean forcePluginOpen;
private boolean isKeyguardShowingAndNotOccluded() {
return keyguardShowing && !keyguardOccluded;
@@ -419,4 +435,13 @@
return result.toString();
}
}
+
+ /**
+ * Custom listener to pipe data back to plugins about whether or not the status bar would be
+ * collapsed if not for the plugin.
+ * TODO: Find cleaner way to do this.
+ */
+ public interface OtherwisedCollapsedListener {
+ void setWouldOtherwiseCollapse(boolean otherwiseCollapse);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index ffc0d97..bb0748c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -19,11 +19,14 @@
import libcore.icu.LocaleData;
import android.app.ActivityManager;
+import android.app.StatusBarManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.res.Configuration;
import android.content.res.TypedArray;
+import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
@@ -35,12 +38,18 @@
import android.text.style.RelativeSizeSpan;
import android.util.AttributeSet;
import android.view.Display;
+import android.view.View;
import android.widget.TextView;
import com.android.systemui.DemoMode;
import com.android.systemui.Dependency;
+import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
+import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -52,10 +61,14 @@
/**
* Digital clock for the status bar.
*/
-public class Clock extends TextView implements DemoMode, Tunable {
+public class Clock extends TextView implements DemoMode, Tunable, CommandQueue.Callbacks,
+ DarkReceiver, ConfigurationListener {
public static final String CLOCK_SECONDS = "clock_seconds";
+ private boolean mClockVisibleByPolicy = true;
+ private boolean mClockVisibleByUser = true;
+
private boolean mAttached;
private Calendar mCalendar;
private String mClockFormatString;
@@ -110,6 +123,8 @@
null, Dependency.get(Dependency.TIME_TICK_HANDLER));
Dependency.get(TunerService.class).addTunable(this, CLOCK_SECONDS,
StatusBarIconController.ICON_BLACKLIST);
+ SysUiServiceProvider.getComponent(getContext(), CommandQueue.class).addCallbacks(this);
+ Dependency.get(DarkIconDispatcher.class).addDarkReceiver(this);
}
// NOTE: It's safe to do these after registering the receiver since the receiver always runs
@@ -130,6 +145,9 @@
getContext().unregisterReceiver(mIntentReceiver);
mAttached = false;
Dependency.get(TunerService.class).removeTunable(this);
+ SysUiServiceProvider.getComponent(getContext(), CommandQueue.class)
+ .removeCallbacks(this);
+ Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(this);
}
}
@@ -158,6 +176,22 @@
}
};
+ public void setClockVisibleByUser(boolean visible) {
+ mClockVisibleByUser = visible;
+ updateClockVisibility();
+ }
+
+ public void setClockVisibilityByPolicy(boolean visible) {
+ mClockVisibleByPolicy = visible;
+ updateClockVisibility();
+ }
+
+ private void updateClockVisibility() {
+ int visibility = (mClockVisibleByPolicy && mClockVisibleByUser)
+ ? View.VISIBLE : View.GONE;
+ setVisibility(visibility);
+ }
+
final void updateClock() {
if (mDemoMode) return;
mCalendar.setTimeInMillis(System.currentTimeMillis());
@@ -170,9 +204,38 @@
if (CLOCK_SECONDS.equals(key)) {
mShowSeconds = newValue != null && Integer.parseInt(newValue) != 0;
updateShowSeconds();
+ } else {
+ setClockVisibleByUser(!StatusBarIconController.getIconBlacklist(newValue)
+ .contains("clock"));
+ updateClockVisibility();
}
}
+ @Override
+ public void disable(int state1, int state2, boolean animate) {
+ boolean clockVisibleByPolicy = (state1 & StatusBarManager.DISABLE_CLOCK) == 0;
+ if (clockVisibleByPolicy != mClockVisibleByPolicy) {
+ setClockVisibilityByPolicy(clockVisibleByPolicy);
+ }
+ }
+
+ @Override
+ public void onDarkChanged(Rect area, float darkIntensity, int tint) {
+ setTextColor(DarkIconDispatcher.getTint(area, this, tint));
+ }
+
+ @Override
+ public void onDensityOrFontScaleChanged() {
+ FontSizeUtils.updateFontSize(this, R.dimen.status_bar_clock_size);
+ setPaddingRelative(
+ mContext.getResources().getDimensionPixelSize(
+ R.dimen.status_bar_clock_starting_padding),
+ 0,
+ mContext.getResources().getDimensionPixelSize(
+ R.dimen.status_bar_clock_end_padding),
+ 0);
+ }
+
private void updateShowSeconds() {
if (mShowSeconds) {
// Wait until we have a display to start trying to show seconds.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
new file mode 100644
index 0000000..788fda8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.content.res.Configuration;
+
+import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
+
+/**
+ * Common listener for configuration or subsets of configuration changes (like density or
+ * font scaling), providing easy static dependence on these events.
+ */
+public interface ConfigurationController extends CallbackController<ConfigurationListener> {
+
+ interface ConfigurationListener {
+ default void onConfigChanged(Configuration newConfig) {}
+ default void onDensityOrFontScaleChanged() {}
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DarkIconDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DarkIconDispatcher.java
new file mode 100644
index 0000000..58944c6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DarkIconDispatcher.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.view.View;
+import android.widget.ImageView;
+
+import com.android.systemui.statusbar.phone.LightBarTransitionsController;
+
+public interface DarkIconDispatcher {
+
+ void setIconsDarkArea(Rect r);
+ LightBarTransitionsController getTransitionsController();
+
+ void addDarkReceiver(DarkReceiver receiver);
+ void addDarkReceiver(ImageView imageView);
+
+ // Must have been previously been added through one of the addDarkReceive methods above.
+ void removeDarkReceiver(DarkReceiver object);
+ void removeDarkReceiver(ImageView object);
+
+ // Used to reapply darkness on an object, must have previously been added through
+ // addDarkReceiver.
+ void applyDark(ImageView object);
+
+ int DEFAULT_ICON_TINT = Color.WHITE;
+ Rect sTmpRect = new Rect();
+ int[] sTmpInt2 = new int[2];
+
+ /**
+ * @return the tint to apply to {@param view} depending on the desired tint {@param color} and
+ * the screen {@param tintArea} in which to apply that tint
+ */
+ static int getTint(Rect tintArea, View view, int color) {
+ if (isInArea(tintArea, view)) {
+ return color;
+ } else {
+ return DEFAULT_ICON_TINT;
+ }
+ }
+
+ /**
+ * @return the dark intensity to apply to {@param view} depending on the desired dark
+ * {@param intensity} and the screen {@param tintArea} in which to apply that intensity
+ */
+ static float getDarkIntensity(Rect tintArea, View view, float intensity) {
+ if (isInArea(tintArea, view)) {
+ return intensity;
+ } else {
+ return 0f;
+ }
+ }
+
+ /**
+ * @return true if more than half of the {@param view} area are in {@param area}, false
+ * otherwise
+ */
+ static boolean isInArea(Rect area, View view) {
+ if (area.isEmpty()) {
+ return true;
+ }
+ sTmpRect.set(area);
+ view.getLocationOnScreen(sTmpInt2);
+ int left = sTmpInt2[0];
+
+ int intersectStart = Math.max(left, area.left);
+ int intersectEnd = Math.min(left + view.getWidth(), area.right);
+ int intersectAmount = Math.max(0, intersectEnd - intersectStart);
+
+ boolean coversFullStatusBar = area.top <= 0;
+ boolean majorityOfWidth = 2 * intersectAmount > view.getWidth();
+ return majorityOfWidth && coversFullStatusBar;
+ }
+
+ interface DarkReceiver {
+ void onDarkChanged(Rect area, float darkIntensity, int tint);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
index de47267..728005d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
@@ -21,8 +21,12 @@
boolean isSecure();
boolean canSkipBouncer();
boolean isShowing();
+ boolean isKeyguardFadingAway();
+ boolean isKeyguardGoingAway();
+ long getKeyguardFadingAwayDuration();
+ long getKeyguardFadingAwayDelay();
public interface Callback {
- void onKeyguardChanged();
+ void onKeyguardShowingChanged();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
index 769f93f..821e635 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
@@ -18,13 +18,10 @@
import android.app.ActivityManager;
import android.content.Context;
-import android.os.RemoteException;
-import android.view.WindowManagerGlobal;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.settings.CurrentUserTracker;
-import com.android.systemui.statusbar.policy.KeyguardMonitor.Callback;
import java.util.ArrayList;
@@ -44,6 +41,10 @@
private boolean mCanSkipBouncer;
private boolean mListening;
+ private boolean mKeyguardFadingAway;
+ private long mKeyguardFadingAwayDelay;
+ private long mKeyguardFadingAwayDuration;
+ private boolean mKeyguardGoingAway;
public KeyguardMonitorImpl(Context context) {
mContext = context;
@@ -115,8 +116,42 @@
}
private void notifyKeyguardChanged() {
- for (Callback callback : mCallbacks) {
- callback.onKeyguardChanged();
- }
+ mCallbacks.forEach(Callback::onKeyguardShowingChanged);
+ }
+
+ public void notifyKeyguardFadingAway(long delay, long fadeoutDuration) {
+ mKeyguardFadingAway = true;
+ mKeyguardFadingAwayDelay = delay;
+ mKeyguardFadingAwayDuration = fadeoutDuration;
+ mCallbacks.forEach(Callback::onKeyguardShowingChanged);
+ }
+
+ public void notifyKeyguardDoneFading() {
+ mKeyguardFadingAway = false;
+ mCallbacks.forEach(Callback::onKeyguardShowingChanged);
+ }
+
+ @Override
+ public boolean isKeyguardFadingAway() {
+ return mKeyguardFadingAway;
+ }
+
+ @Override
+ public boolean isKeyguardGoingAway() {
+ return mKeyguardGoingAway;
+ }
+
+ @Override
+ public long getKeyguardFadingAwayDelay() {
+ return mKeyguardFadingAwayDelay;
+ }
+
+ @Override
+ public long getKeyguardFadingAwayDuration() {
+ return mKeyguardFadingAwayDuration;
+ }
+
+ public void notifyKeyguardGoingAway(boolean keyguardGoingAway) {
+ mKeyguardGoingAway = keyguardGoingAway;
}
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 7a32bf1..6df4a21 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -850,7 +850,7 @@
private final KeyguardMonitor.Callback mCallback = new KeyguardMonitor.Callback() {
@Override
- public void onKeyguardChanged() {
+ public void onKeyguardShowingChanged() {
notifyAdapters();
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
index f195f7a..8777aa6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
@@ -36,14 +36,14 @@
int getCurrentUser();
boolean isVolumeRestricted();
- public static class Callback {
- public void onZenChanged(int zen) {}
- public void onConditionsChanged(Condition[] conditions) {}
- public void onNextAlarmChanged() {}
- public void onZenAvailableChanged(boolean available) {}
- public void onEffectsSupressorChanged() {}
- public void onManualRuleChanged(ZenRule rule) {}
- public void onConfigChanged(ZenModeConfig config) {}
+ public static interface Callback {
+ default void onZenChanged(int zen) {}
+ default void onConditionsChanged(Condition[] conditions) {}
+ default void onNextAlarmChanged() {}
+ default void onZenAvailableChanged(boolean available) {}
+ default void onEffectsSupressorChanged() {}
+ default void onManualRuleChanged(ZenRule rule) {}
+ default void onConfigChanged(ZenModeConfig config) {}
}
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
index ca582b3..0edff86 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
@@ -38,10 +38,11 @@
import android.util.ArrayMap;
import android.util.ArraySet;
-import com.android.systemui.BatteryMeterDrawable;
+import static com.android.systemui.BatteryMeterDrawable.SHOW_PERCENT_SETTING;
import com.android.systemui.DemoMode;
import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIApplication;
import com.android.systemui.settings.CurrentUserTracker;
@@ -200,7 +201,8 @@
public void clearAll() {
// A couple special cases.
Settings.Global.putString(mContentResolver, DemoMode.DEMO_MODE_ALLOWED, null);
- Settings.System.putString(mContentResolver, BatteryMeterDrawable.SHOW_PERCENT_SETTING, null);
+ Settings.System.putString(mContentResolver,
+ SHOW_PERCENT_SETTING, null);
Intent intent = new Intent(DemoMode.ACTION_DEMO);
intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_EXIT);
mContext.sendBroadcast(intent);
diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml
index 6d62435..41b75ff 100644
--- a/packages/SystemUI/tests/AndroidManifest.xml
+++ b/packages/SystemUI/tests/AndroidManifest.xml
@@ -35,6 +35,7 @@
<uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
<uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
<uses-permission android:name="android.permission.REQUEST_NETWORK_SCORES" />
+ <uses-permission android:name="android.permission.CONTROL_VPN" />
<application>
<uses-library android:name="android.test.runner" />
diff --git a/packages/SystemUI/tests/src/com/android/systemui/BatteryMeterDrawableTest.java b/packages/SystemUI/tests/src/com/android/systemui/BatteryMeterDrawableTest.java
index cb0f7a38..09808d4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/BatteryMeterDrawableTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/BatteryMeterDrawableTest.java
@@ -16,7 +16,6 @@
package com.android.systemui;
-import static junit.framework.Assert.assertEquals;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyFloat;
@@ -51,24 +50,6 @@
}
@Test
- public void testGetIntrinsicSize() {
- assertEquals(
- mResources.getDimensionPixelSize(R.dimen.battery_width),
- mBatteryMeter.getIntrinsicWidth());
- assertEquals(
- mResources.getDimensionPixelSize(R.dimen.battery_height),
- mBatteryMeter.getIntrinsicHeight());
- }
-
- @Test
- public void testDrawNothingBeforeOnBatteryLevelChanged() {
- final Canvas canvas = mock(Canvas.class);
- mBatteryMeter.draw(canvas);
- verify(canvas, never()).drawPath(any(), any());
- verify(canvas, never()).drawText(anyString(), anyFloat(), anyFloat(), any());
- }
-
- @Test
public void testDrawImageButNoTextIfPluggedIn() {
mBatteryMeter.onBatteryLevelChanged(0, true, true);
final Canvas canvas = mock(Canvas.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
index 81a50d9..12a485e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
@@ -18,11 +18,12 @@
import static org.mockito.Mockito.mock;
import android.content.Context;
-import android.support.test.InstrumentationRegistry;
import android.os.Handler;
import android.os.Looper;
import android.os.MessageQueue;
+import android.support.test.InstrumentationRegistry;
import android.util.ArrayMap;
+import android.util.Log;
import com.android.systemui.utils.TestableContext;
import com.android.systemui.utils.leaks.Tracker;
@@ -30,17 +31,21 @@
import org.junit.After;
import org.junit.Before;
+import java.lang.Thread.UncaughtExceptionHandler;
+
/**
* Base class that does System UI specific setup.
*/
public abstract class SysuiTestCase {
+ private Throwable mException;
private Handler mHandler;
protected TestableContext mContext;
protected TestDependency mDependency;
@Before
public void SysuiSetup() throws Exception {
+ mException = null;
System.setProperty("dexmaker.share_classloader", "true");
mContext = new TestableContext(InstrumentationRegistry.getTargetContext(), this);
SystemUIFactory.createFromConfig(mContext);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index f22c1af..9eac0a0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -24,14 +24,18 @@
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.tuner.TunerService;
+import com.android.systemui.util.LayoutInflaterBuilder;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.support.test.runner.AndroidJUnit4;
+import android.view.View;
+import android.widget.FrameLayout;
@RunWith(AndroidJUnit4.class)
public class QSFragmentTest extends FragmentTestCase {
@@ -42,6 +46,13 @@
@Before
public void addLeakCheckDependencies() {
+ mContext.addMockSystemService(Context.LAYOUT_INFLATER_SERVICE,
+ new LayoutInflaterBuilder(mContext)
+ .replace("com.android.systemui.statusbar.policy.SplitClockView",
+ FrameLayout.class)
+ .replace("TextClock", View.class)
+ .build());
+
injectTestDependency(Dependency.BG_LOOPER, Looper.getMainLooper());
injectMockDependency(UserSwitcherController.class);
injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
index 5b22986..930e560 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
@@ -41,6 +41,7 @@
mCommandQueue = new CommandQueue();
mCallbacks = mock(Callbacks.class);
mCommandQueue.addCallbacks(mCallbacks);
+ verify(mCallbacks).disable(eq(0), eq(0), eq(false));
}
@After
@@ -181,7 +182,7 @@
public void testAppTransitionPending() {
mCommandQueue.appTransitionPending();
waitForIdleSync();
- verify(mCallbacks).appTransitionPending();
+ verify(mCallbacks).appTransitionPending(eq(false));
}
@Test
@@ -195,7 +196,7 @@
public void testAppTransitionStarting() {
mCommandQueue.appTransitionStarting(1, 2);
waitForIdleSync();
- verify(mCallbacks).appTransitionStarting(eq(1L), eq(2L));
+ verify(mCallbacks).appTransitionStarting(eq(1L), eq(2L), eq(false));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
new file mode 100644
index 0000000..cb30df4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.app.StatusBarManager;
+import android.view.View;
+import android.view.ViewPropertyAnimator;
+
+import com.android.systemui.FragmentTestCase;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.SecurityController;
+import com.android.systemui.tuner.TunerService;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class CollapsedStatusBarFragmentTest extends FragmentTestCase {
+
+ private NotificationIconAreaController mMockNotificiationAreaController;
+ private View mNotificationAreaInner;
+
+ public CollapsedStatusBarFragmentTest() {
+ super(CollapsedStatusBarFragment.class);
+ }
+
+ @Before
+ public void setup() {
+ mContext.putComponent(CommandQueue.class, mock(CommandQueue.class));
+ mContext.putComponent(StatusBar.class, mock(StatusBar.class));
+ mContext.putComponent(TunerService.class, mock(TunerService.class));
+ injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
+ mMockNotificiationAreaController = mock(NotificationIconAreaController.class);
+ mNotificationAreaInner = mock(View.class);
+ when(mNotificationAreaInner.animate()).thenReturn(mock(ViewPropertyAnimator.class));
+ when(mMockNotificiationAreaController.getNotificationInnerAreaView()).thenReturn(
+ mNotificationAreaInner);
+ }
+
+ @Test
+ public void testDisableNone() throws Exception {
+ postAndWait(() -> mFragments.dispatchResume());
+
+ CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
+ fragment.initNotificationIconArea(mMockNotificiationAreaController);
+ fragment.disable(0, 0, false);
+
+ assertEquals(View.VISIBLE, mFragment.getView().findViewById(R.id.system_icon_area)
+ .getVisibility());
+ }
+
+ @Test
+ public void testDisableSystemInfo() throws Exception {
+ postAndWait(() -> mFragments.dispatchResume());
+
+ CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
+ fragment.initNotificationIconArea(mMockNotificiationAreaController);
+ fragment.disable(StatusBarManager.DISABLE_SYSTEM_INFO, 0, false);
+
+ assertEquals(View.INVISIBLE, mFragment.getView().findViewById(R.id.system_icon_area)
+ .getVisibility());
+
+ fragment.disable(0, 0, false);
+
+ assertEquals(View.VISIBLE, mFragment.getView().findViewById(R.id.system_icon_area)
+ .getVisibility());
+ }
+
+ @Test
+ public void testDisableNotifications() throws Exception {
+ postAndWait(() -> mFragments.dispatchResume());
+
+ CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
+ fragment.initNotificationIconArea(mMockNotificiationAreaController);
+ fragment.disable(StatusBarManager.DISABLE_NOTIFICATION_ICONS, 0, false);
+
+ Mockito.verify(mNotificationAreaInner).setVisibility(eq(View.INVISIBLE));
+
+ fragment.disable(0, 0, false);
+
+ Mockito.verify(mNotificationAreaInner).setVisibility(eq(View.VISIBLE));
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
index a9d6df7..3bce64f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
@@ -15,10 +15,14 @@
package com.android.systemui.statusbar.phone;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import android.content.Context;
+import android.os.Looper;
+import android.view.Display;
import android.view.WindowManager;
+import com.android.systemui.Dependency;
import com.android.systemui.FragmentTestCase;
import com.android.systemui.recents.Recents;
import com.android.systemui.stackdivider.Divider;
@@ -35,17 +39,21 @@
@Before
public void setup() {
+ injectTestDependency(Dependency.BG_LOOPER, Looper.getMainLooper());
mContext.putComponent(CommandQueue.class, mock(CommandQueue.class));
mContext.putComponent(StatusBar.class, mock(StatusBar.class));
mContext.putComponent(Recents.class, mock(Recents.class));
mContext.putComponent(Divider.class, mock(Divider.class));
- mContext.addMockSystemService(Context.WINDOW_SERVICE, mock(WindowManager.class));
injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
+ WindowManager windowManager = mock(WindowManager.class);
+ Display defaultDisplay = mContext.getSystemService(WindowManager.class).getDefaultDisplay();
+ when(windowManager.getDefaultDisplay()).thenReturn(
+ defaultDisplay);
+ mContext.addMockSystemService(Context.WINDOW_SERVICE, windowManager);
}
@Test
public void testHomeLongPress() {
- mContext.addMockSystemService(Context.WINDOW_SERVICE, mock(WindowManager.class));
NavigationBarFragment navigationBarFragment = (NavigationBarFragment) mFragment;
postAndWait(() -> mFragments.dispatchResume());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/TestableContext.java b/packages/SystemUI/tests/src/com/android/systemui/utils/TestableContext.java
index 62c007f..c4f1003 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/TestableContext.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/TestableContext.java
@@ -30,6 +30,7 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.util.ArrayMap;
+import android.view.LayoutInflater;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.utils.leaks.Tracker;
@@ -99,6 +100,9 @@
if (mMockSystemServices != null && mMockSystemServices.containsKey(name)) {
return mMockSystemServices.get(name);
}
+ if (name.equals(LAYOUT_INFLATER_SERVICE)) {
+ return getBaseContext().getSystemService(LayoutInflater.class).cloneInContext(this);
+ }
return super.getSystemService(name);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
index 39bbf2d..21871fc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
@@ -45,6 +45,26 @@
}
@Override
+ public boolean isKeyguardFadingAway() {
+ return false;
+ }
+
+ @Override
+ public boolean isKeyguardGoingAway() {
+ return false;
+ }
+
+ @Override
+ public long getKeyguardFadingAwayDuration() {
+ return 0;
+ }
+
+ @Override
+ public long getKeyguardFadingAwayDelay() {
+ return 0;
+ }
+
+ @Override
public boolean canSkipBouncer() {
return false;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
new file mode 100644
index 0000000..b13535f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.utils.leaks;
+
+import com.android.internal.statusbar.StatusBarIcon;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.StatusBarIconController.IconManager;
+
+public class FakeStatusBarIconController extends BaseLeakChecker<IconManager>
+ implements StatusBarIconController {
+
+ public FakeStatusBarIconController(LeakCheckedTest test) {
+ super(test, "StatusBarGroup");
+ }
+
+ @Override
+ public void addIconGroup(IconManager iconManager) {
+ addCallback(iconManager);
+ }
+
+ @Override
+ public void removeIconGroup(IconManager iconManager) {
+ removeCallback(iconManager);
+ }
+
+ @Override
+ public void setExternalIcon(String slot) {
+
+ }
+
+ @Override
+ public void setIcon(String slot, int resourceId, CharSequence contentDescription) {
+
+ }
+
+ @Override
+ public void setIcon(String slot, StatusBarIcon icon) {
+
+ }
+
+ @Override
+ public void setIconVisibility(String slotTty, boolean b) {
+
+ }
+
+ @Override
+ public void removeIcon(String slot) {
+
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakCheckedTest.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakCheckedTest.java
index c2048c7..6ff8098 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakCheckedTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakCheckedTest.java
@@ -22,6 +22,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.PluginManager;
import com.android.systemui.statusbar.phone.ManagedProfileController;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.CallbackController;
@@ -75,6 +76,7 @@
NetworkController.class,
PluginManager.class,
TunerService.class,
+ StatusBarIconController.class,
};
@Rule
@@ -121,6 +123,8 @@
obj = new FakePluginManager(mContext, this);
} else if (cls == TunerService.class) {
obj = new FakeTunerService(mContext, this);
+ } else if (cls == StatusBarIconController.class) {
+ obj = new FakeStatusBarIconController(this);
} else {
Assert.fail(cls.getName() + " is not supported by LeakCheckedTest yet");
}
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index a590805..e4b53cb 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3388,6 +3388,9 @@
// OS: O
FIELD_GESTURE_VELOCITY = 827;
+ // OPEN: Carrier demo mode password dialog
+ CARRIER_DEMO_MODE_PASSWORD = 828;
+
// ---- End O Constants, all O constants go above this line ----
// Add new aosp constants above this line.
diff --git a/services/autofill/java/com/android/server/autofill/AnchoredWindow.java b/services/autofill/java/com/android/server/autofill/AnchoredWindow.java
index c68ac60..ed0d234 100644
--- a/services/autofill/java/com/android/server/autofill/AnchoredWindow.java
+++ b/services/autofill/java/com/android/server/autofill/AnchoredWindow.java
@@ -17,134 +17,276 @@
import static com.android.server.autofill.Helper.DEBUG;
+import android.annotation.Nullable;
import android.content.Context;
+import android.graphics.PixelFormat;
import android.graphics.Rect;
+import android.os.IBinder;
import android.util.Slog;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewGroup;
+import android.view.View.MeasureSpec;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.FrameLayout;
-import java.io.PrintWriter;
/**
* A window above the application that is smartly anchored to a rectangular region.
*/
-final class AnchoredWindow {
+final class AnchoredWindow implements View.OnLayoutChangeListener, View.OnTouchListener {
private static final String TAG = "AutoFill";
+ private static final int NULL_HEIGHT = -1;
+
private final WindowManager mWm;
- private final View mRootView;
- private final View mView;
- private final int mWidth;
- private final int mHeight;
- private boolean mIsShowing = false;
+ private final IBinder mAppToken;
+ private final View mContentView;
+
+ private final View mWindowSizeListenerView;
+ private final int mMinMargin;
+
+ private int mLastHeight = NULL_HEIGHT;
+ @Nullable
+ private Rect mLastBounds;
+ @Nullable
+ private Rect mLastDisplayBounds;
/**
* Constructor.
*
- * @param wm window manager that draws the view on a window
- * @param view singleton view in the window
- * @param width requested width of the view
- * @param height requested height of the view
+ * @param wm window manager that draws the content on a window
+ * @param appToken token to pass to window manager
+ * @param contentView content of the window
*/
- AnchoredWindow(WindowManager wm, View view, int width, int height) {
+ AnchoredWindow(WindowManager wm, IBinder appToken, View contentView) {
mWm = wm;
- mRootView = wrapView(view, width, height);
- mView = view;
- mWidth = width;
- mHeight = height;
+ mAppToken = appToken;
+ mContentView = contentView;
+
+ mContentView.addOnLayoutChangeListener(this);
+
+ Context context = contentView.getContext();
+
+ mWindowSizeListenerView = new FrameLayout(context);
+ mWindowSizeListenerView.addOnLayoutChangeListener(this);
+
+ mMinMargin = context.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.autofill_fill_min_margin);
}
/**
* Shows the window.
*
- * @param bounds the rectangular region this window should be anchored to
+ * @param bounds the region the window should be anchored to
*/
void show(Rect bounds) {
- final LayoutParams params = createBaseLayoutParams();
- params.x = bounds.left;
- params.y = bounds.bottom;
+ if (DEBUG) Slog.d(TAG, "show bounds=" + bounds);
- if (!mIsShowing) {
- if (DEBUG) Slog.d(TAG, "adding view " + mView);
- mWm.addView(mRootView, params);
- } else {
- if (DEBUG) Slog.d(TAG, "updating view " + mView);
- mWm.updateViewLayout(mRootView, params);
+ if (!mWindowSizeListenerView.isAttachedToWindow()) {
+ if (DEBUG) Slog.d(TAG, "adding mWindowSizeListenerView");
+ LayoutParams params = createWindowLayoutParams(
+ mAppToken,
+ LayoutParams.FLAG_NOT_TOUCHABLE); // not touchable
+ params.gravity = Gravity.LEFT | Gravity.TOP;
+ params.x = 0;
+ params.y = 0;
+ params.width = LayoutParams.MATCH_PARENT;
+ params.height = LayoutParams.MATCH_PARENT;
+ mWm.addView(mWindowSizeListenerView, params);
}
- mIsShowing = true;
+
+ updateBounds(bounds);
}
/**
* Hides the window.
*/
void hide() {
- if (DEBUG) Slog.d(TAG, "removing view " + mView);
+ if (DEBUG) Slog.d(TAG, "hide");
- if (mIsShowing) {
- mWm.removeView(mRootView);
+ mLastHeight = NULL_HEIGHT;
+ mLastBounds = null;
+ mLastDisplayBounds = null;
+
+ if (mWindowSizeListenerView.isAttachedToWindow()) {
+ if (DEBUG) Slog.d(TAG, "removing mWindowSizeListenerView");
+ mWm.removeView(mWindowSizeListenerView);
}
- mIsShowing = false;
- }
- /**
- * Wraps a view with a SelfRemovingView and sets its requested width and height.
- */
- private View wrapView(View view, int width, int height) {
- final ViewGroup viewGroup = new SelfRemovingView(view.getContext());
- viewGroup.addView(view, new ViewGroup.LayoutParams(width, height));
- return viewGroup;
- }
-
- private static LayoutParams createBaseLayoutParams() {
- final LayoutParams params = new LayoutParams();
- // TODO(b/33197203): LayoutParams.TYPE_AUTOFILL
- params.type = LayoutParams.TYPE_SYSTEM_ALERT;
- params.flags =
- LayoutParams.SOFT_INPUT_STATE_UNCHANGED
- | LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | LayoutParams.FLAG_LAYOUT_NO_LIMITS
- | LayoutParams.FLAG_NOT_FOCUSABLE
- | LayoutParams.FLAG_NOT_TOUCH_MODAL
- | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
- params.gravity = Gravity.TOP | Gravity.LEFT;
- params.width = LayoutParams.WRAP_CONTENT;
- params.height = LayoutParams.WRAP_CONTENT;
- return params;
+ if (mContentView.isAttachedToWindow()) {
+ if (DEBUG) Slog.d(TAG, "removing mContentView");
+ mContentView.setOnTouchListener(null);
+ mWm.removeView(mContentView);
+ }
}
@Override
- public String toString() {
- if (!DEBUG) return super.toString();
-
- return "AnchoredWindow: [width=" + mWidth + ", height=" + mHeight + ", view=" + mView + "]";
+ public void onLayoutChange(View view, int left, int top, int right, int bottom,
+ int oldLeft, int oldTop, int oldRight, int oldBottom) {
+ if (view == mWindowSizeListenerView) {
+ if (DEBUG) Slog.d(TAG, "onLayoutChange() for mWindowSizeListenerView");
+ // mWindowSizeListenerView layout changed, get the size of the display bounds and update
+ // the window.
+ final Rect displayBounds = new Rect();
+ view.getBoundsOnScreen(displayBounds);
+ updateDisplayBounds(displayBounds);
+ } else if (view == mContentView) {
+ // mContentView layout changed, update the window in case its height changed.
+ if (DEBUG) Slog.d(TAG, "onLayoutChange() for mContentView");
+ updateHeight();
+ }
}
- void dump(PrintWriter pw) {
- pw.println("Anchored Window");
- final String prefix = " ";
- pw.print(prefix); pw.print("width: "); pw.println(mWidth);
- pw.print(prefix); pw.print("height: "); pw.println(mHeight);
- pw.print(prefix); pw.print("visible: "); pw.println(mIsShowing);
+ // When the window is touched outside, hide the window.
+ @Override
+ public boolean onTouch(View view, MotionEvent event) {
+ if (view == mContentView && event.getAction() == MotionEvent.ACTION_OUTSIDE) {
+ hide();
+ return true;
+ }
+ return false;
}
- /** FrameLayout that listens for touch events removes itself if the touch event is outside. */
- private final class SelfRemovingView extends FrameLayout {
- public SelfRemovingView(Context context) {
- super(context);
+ private boolean updateHeight() {
+ final Rect displayBounds = mLastDisplayBounds;
+ if (displayBounds == null) {
+ return false;
}
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
- hide();
- return true;
- } else {
- return super.onTouchEvent(event);
+ mContentView.measure(
+ MeasureSpec.makeMeasureSpec(displayBounds.width(), MeasureSpec.AT_MOST),
+ MeasureSpec.makeMeasureSpec(displayBounds.height(), MeasureSpec.AT_MOST));
+ int height = mContentView.getMeasuredHeight();
+ if (height != mLastHeight) {
+ if (DEBUG) Slog.d(TAG, "update height=" + height);
+ mLastHeight = height;
+ update(height, mLastBounds, displayBounds);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private void updateBounds(Rect bounds) {
+ if (!bounds.equals(mLastBounds)) {
+ if (DEBUG) Slog.d(TAG, "update bounds=" + bounds);
+ mLastBounds = bounds;
+
+ update(mLastHeight, bounds, mLastDisplayBounds);
+ }
+ }
+
+ private void updateDisplayBounds(Rect displayBounds) {
+ if (!displayBounds.equals(mLastDisplayBounds)) {
+ if (DEBUG) Slog.d(TAG, "update displayBounds=" + displayBounds);
+ mLastDisplayBounds = displayBounds;
+
+ if (!updateHeight()) {
+ update(mLastHeight, mLastBounds, displayBounds);
}
}
}
+
+ // Updates the window if height, bounds, and displayBounds are not null.
+ // Caller should ensure that something changed before calling.
+ private void update(int height, @Nullable Rect bounds, @Nullable Rect displayBounds) {
+ if (height == NULL_HEIGHT || bounds == null || displayBounds == null) {
+ return;
+ }
+
+ if (DEBUG) Slog.d(TAG, "update height=" + height + ", bounds=" + bounds
+ + ", displayBounds=" + displayBounds);
+
+ final LayoutParams params = createWindowLayoutParams(mAppToken,
+ LayoutParams.FLAG_NOT_TOUCH_MODAL // outside touches go to windows behind us
+ | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH); // outside touches trigger MotionEvent
+ params.setTitle("AutoFill Fill"); // used for debugging
+ updatePosition(params, height, mMinMargin, bounds, displayBounds);
+ if (!mContentView.isAttachedToWindow()) {
+ if (DEBUG) Slog.d(TAG, "adding mContentView");
+ mWm.addView(mContentView, params);
+ mContentView.setOnTouchListener(this);
+ } else {
+ if (DEBUG) Slog.d(TAG, "updating mContentView");
+ mWm.updateViewLayout(mContentView, params);
+ }
+ }
+
+ /**
+ * Updates the position of the window by altering the {@link LayoutParams}.
+ *
+ * <p>The window can be anchored either above or below the bounds. Anchoring the window below
+ * the bounds is preferred, if it fits. Otherwise, anchor the window on the side with more
+ * space.
+ *
+ * @param params the params to update
+ * @param height the requested height of the window
+ * @param minMargin the minimum margin between the window and the display bounds
+ * @param bounds the region the window should be anchored to
+ * @param displayBounds the region in which the window may be displayed
+ */
+ private static void updatePosition(
+ LayoutParams params,
+ int height,
+ int minMargin,
+ Rect bounds,
+ Rect displayBounds) {
+ boolean below;
+ int verticalSpace;
+ final int verticalSpaceBelow = displayBounds.bottom - bounds.bottom - minMargin;
+ if (height <= verticalSpaceBelow) {
+ // Fits below bounds.
+ below = true;
+ verticalSpace = height;
+ } else {
+ final int verticalSpaceAbove = bounds.top - displayBounds.top - minMargin;
+ if (height <= verticalSpaceAbove) {
+ // Fits above bounds.
+ below = false;
+ verticalSpace = height;
+ } else {
+ // Pick above/below based on which has the most space.
+ if (verticalSpaceBelow >= verticalSpaceAbove) {
+ below = true;
+ verticalSpace = verticalSpaceBelow;
+ } else {
+ below = false;
+ verticalSpace = verticalSpaceAbove;
+ }
+ }
+ }
+
+ int gravity;
+ int y;
+ if (below) {
+ if (DEBUG) Slog.d(TAG, "anchorBelow");
+ gravity = Gravity.TOP | Gravity.LEFT;
+ y = bounds.bottom - displayBounds.top;
+ } else {
+ if (DEBUG) Slog.d(TAG, "anchorAbove");
+ gravity = Gravity.BOTTOM | Gravity.LEFT;
+ y = displayBounds.bottom - bounds.top;
+ }
+
+ final int x = bounds.left - displayBounds.left;
+
+ params.gravity = gravity;
+ params.x = x;
+ params.y = y;
+ params.width = bounds.width();
+ params.height = verticalSpace;
+ }
+
+ private static LayoutParams createWindowLayoutParams(IBinder appToken, int flags) {
+ final LayoutParams params = new LayoutParams();
+ params.token = appToken;
+ params.type = LayoutParams.TYPE_PHONE;
+ params.flags =
+ flags
+ | LayoutParams.FLAG_NOT_FOCUSABLE // don't receive input events
+ | LayoutParams.FLAG_ALT_FOCUSABLE_IM; // resize for soft input
+ params.format = PixelFormat.TRANSLUCENT;
+ return params;
+ }
}
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
index 88f1bda..859e1a1 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
@@ -165,6 +165,17 @@
session.mStructure = structure;
}
+
+ // TODO(b/33197203, b/33269702): Must fetch the data so it's available later on
+ // handleSave(), even if if the activity is gone by then, but structure.ensureData()
+ // gives a ONE_WAY warning because system_service could block on app calls.
+ // We need to change AssistStructure so it provides a "one-way" writeToParcel()
+ // method that sends all the data
+ structure.ensureData();
+
+ // Sanitize structure before it's sent to service.
+ structure.sanitizeForParceling(true);
+
// TODO(b/33197203): Need to pipe the bundle
session.mRemoteFillService.onFillRequest(structure, null);
}
@@ -541,6 +552,11 @@
Slog.wtf(TAG, "showSaveLocked(): no mStructure");
return;
}
+ if (mCurrentResponse == null) {
+ // Happens when the activity / session was finished before the service replied.
+ Slog.d(TAG, "showSaveLocked(): no mCurrentResponse yet");
+ return;
+ }
final ArraySet<AutoFillId> savableIds = mCurrentResponse.getSavableIds();
if (VERBOSE) Slog.v(TAG, "showSaveLocked(): savableIds=" + savableIds);
@@ -562,7 +578,6 @@
Slog.d(TAG, "finishSessionLocked(): found a change on " + id + ": "
+ state.mAutoFillValue);
}
-
mUi.showSaveUi();
return;
}
@@ -709,7 +724,9 @@
filterText = text.toString();
}
}
- getUiForShowing().showFillUi(viewState, response.getDatasets(), bounds, filterText);
+
+ getUiForShowing().showFillUi(mActivityToken, viewState, response.getDatasets(),
+ bounds, filterText);
}
private void processResponseLocked(FillResponse response) {
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/AutoFillUI.java
index c482c40..e9fc044 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillUI.java
@@ -17,6 +17,7 @@
import static com.android.server.autofill.Helper.DEBUG;
+import android.annotation.Nullable;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -71,8 +72,6 @@
private AnchoredWindow mFillWindow;
private DatasetPicker mFillView;
private ViewState mViewState;
- private Rect mBounds;
- private String mFilterText;
private AutoFillUiCallback mCallback;
private IBinder mActivityToken;
@@ -138,8 +137,6 @@
}
mViewState = null;
- mBounds = null;
- mFilterText = null;
mFillView = null;
mFillWindow = null;
}
@@ -147,17 +144,23 @@
/**
* Shows the fill UI, removing the previous fill UI if the has changed.
*
+ * @param appToken the token of the app to be autofilled
* @param viewState the view state, compared by reference to know if new UI should be shown
* @param datasets the datasets to show, not used if viewState is the same
* @param bounds bounds of the view to be filled, used if changed
* @param filterText text of the view to be filled, used if changed
*/
- void showFillUi(ViewState viewState, ArraySet<Dataset> datasets, Rect bounds,
- String filterText) {
+ void showFillUi(IBinder appToken, ViewState viewState, @Nullable ArraySet<Dataset> datasets,
+ Rect bounds, String filterText) {
if (!hasCallback()) {
return;
}
+ UiThread.getHandler().runWithScissors(() -> {
+ hideSnackbarUiThread();
+ hideFillResponseAuthUiUiThread();
+ }, 0);
+
if (datasets == null) {
// TODO(b/33197203): shouldn't be called, but keeping the WTF for a while just to be
// safe, otherwise it would crash system server...
@@ -165,13 +168,10 @@
return;
}
- // TODO(b/33197203): call to hideAll() was making it janky because then mViewState is set
- // to null and hence the first check inside the lambada fails, causing it to be displayed
- // twice in some cases.
- hideAll();
-
UiThread.getHandler().runWithScissors(() -> {
if (mViewState == null || !mViewState.mId.equals(viewState.mId)) {
+ hideFillUiUiThread();
+
mViewState = viewState;
mFillView = new DatasetPicker(mContext, datasets,
@@ -183,25 +183,15 @@
callback.fill(dataset);
hideFillUi();
});
- // TODO(b/33197203): No magical numbers
- mFillWindow = new AnchoredWindow(
- mWm, mFillView, 800, ViewGroup.LayoutParams.WRAP_CONTENT);
- if (DEBUG) Slog.d(TAG, "show FillUi: " + viewState.mId);
+ mFillWindow = new AnchoredWindow(mWm, appToken, mFillView);
+
+ if (DEBUG) Slog.d(TAG, "showFillUi(): view changed");
}
- // TODO(b/33197203): If bounds are the same we would not show, fix this
- if (!bounds.equals(mBounds)) {
- if (DEBUG) Slog.d(TAG, "update FillUi bounds: " + mBounds);
- mBounds = bounds;
- mFillWindow.show(mBounds);
- }
-
- if (!filterText.equals(mFilterText)) {
- if (DEBUG) Slog.d(TAG, "update FillUi filter text: " + mFilterText);
- mFilterText = filterText;
- mFillView.update(mFilterText);
- }
+ if (DEBUG) Slog.d(TAG, "showFillUi(): bounds=" + bounds + ", filterText=" + filterText);
+ mFillView.update(filterText);
+ mFillWindow.show(bounds);
}, 0);
}
@@ -268,8 +258,6 @@
pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken);
pw.print(prefix); pw.print("mSnackBar: "); pw.println(mSnackbar);
pw.print(prefix); pw.print("mViewState: "); pw.println(mViewState);
- pw.print(prefix); pw.print("mBounds: "); pw.println(mBounds);
- pw.print(prefix); pw.print("mFilterText: "); pw.println(mFilterText);
}
//similar to a snackbar, but can be a bit custom since it is more than just text. This will
diff --git a/services/autofill/java/com/android/server/autofill/DatasetPicker.java b/services/autofill/java/com/android/server/autofill/DatasetPicker.java
index 8212cf1..9bee61a 100644
--- a/services/autofill/java/com/android/server/autofill/DatasetPicker.java
+++ b/services/autofill/java/com/android/server/autofill/DatasetPicker.java
@@ -17,6 +17,7 @@
import android.content.Context;
import android.graphics.Color;
+import android.text.TextUtils;
import android.util.ArraySet;
import android.view.autofill.Dataset;
import android.view.View;
@@ -62,8 +63,10 @@
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final TextView textView = (TextView) super.getView(position, convertView, parent);
+ textView.setSingleLine();
+ textView.setEllipsize(TextUtils.TruncateAt.END);
textView.setMinHeight(
- getDimen(com.android.internal.R.dimen.autofill_fill_item_height));
+ getDimen(com.android.internal.R.dimen.autofill_fill_item_height));
return textView;
}
};
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 22eca77..08cb109 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -1297,7 +1297,8 @@
return flags;
}
- InputBindResult attachNewInputLocked(boolean initial) {
+ InputBindResult attachNewInputLocked(
+ /* @InputMethodClient.StartInputReason */ final int startInputReason, boolean initial) {
if (!mBoundToMethod) {
executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
MSG_BIND_INPUT, mCurMethod, mCurClient.binding));
@@ -1361,12 +1362,13 @@
}
return startInputUncheckedLocked(cs, inputContext, missingMethods, attribute,
- controlFlags);
+ controlFlags, startInputReason);
}
InputBindResult startInputUncheckedLocked(@NonNull ClientState cs, IInputContext inputContext,
/* @InputConnectionInspector.missingMethods */ final int missingMethods,
- @NonNull EditorInfo attribute, int controlFlags) {
+ @NonNull EditorInfo attribute, int controlFlags,
+ /* @InputMethodClient.StartInputReason */ final int startInputReason) {
// If no method is currently selected, do nothing.
if (mCurMethodId == null) {
return mNoBinding;
@@ -1408,7 +1410,7 @@
if (cs.curSession != null) {
// Fast case: if we are already connected to the input method,
// then just return it.
- return attachNewInputLocked(
+ return attachNewInputLocked(startInputReason,
(controlFlags&InputMethodManager.CONTROL_START_INITIAL) != 0);
}
if (mHaveConnection) {
@@ -1549,7 +1551,8 @@
clearClientSessionLocked(mCurClient);
mCurClient.curSession = new SessionState(mCurClient,
method, session, channel);
- InputBindResult res = attachNewInputLocked(true);
+ InputBindResult res = attachNewInputLocked(
+ InputMethodClient.START_INPUT_REASON_SESSION_CREATED_BY_IME, true);
if (res.method != null) {
executeOrSendMessage(mCurClient.client, mCaller.obtainMessageOO(
MSG_BIND_CLIENT, mCurClient.client, res));
@@ -2289,7 +2292,7 @@
}
if (attribute != null) {
return startInputUncheckedLocked(cs, inputContext, missingMethods,
- attribute, controlFlags);
+ attribute, controlFlags, startInputReason);
}
return null;
}
@@ -2339,7 +2342,7 @@
if (DEBUG) Slog.v(TAG, "Unspecified window will show input");
if (attribute != null) {
res = startInputUncheckedLocked(cs, inputContext,
- missingMethods, attribute, controlFlags);
+ missingMethods, attribute, controlFlags, startInputReason);
didStart = true;
}
showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
@@ -2365,7 +2368,7 @@
if (DEBUG) Slog.v(TAG, "Window asks to show input going forward");
if (attribute != null) {
res = startInputUncheckedLocked(cs, inputContext,
- missingMethods, attribute, controlFlags);
+ missingMethods, attribute, controlFlags, startInputReason);
didStart = true;
}
showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
@@ -2375,7 +2378,7 @@
if (DEBUG) Slog.v(TAG, "Window asks to always show input");
if (attribute != null) {
res = startInputUncheckedLocked(cs, inputContext, missingMethods,
- attribute, controlFlags);
+ attribute, controlFlags, startInputReason);
didStart = true;
}
showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
@@ -2384,7 +2387,7 @@
if (!didStart && attribute != null) {
res = startInputUncheckedLocked(cs, inputContext, missingMethods, attribute,
- controlFlags);
+ controlFlags, startInputReason);
}
}
} finally {
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 8ef34dc..a073d8e 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -68,6 +68,7 @@
import android.service.gatekeeper.GateKeeperResponse;
import android.service.gatekeeper.IGateKeeperService;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;
@@ -94,8 +95,10 @@
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -231,7 +234,7 @@
}
// Do not tie it to parent when parent does not have a screen lock
final int parentId = mUserManager.getProfileParent(managedUserId).id;
- if (!mStorage.hasPassword(parentId) && !mStorage.hasPattern(parentId)) {
+ if (!isUserSecure(parentId)) {
if (DEBUG) Slog.v(TAG, "Parent does not have a screen lock");
return;
}
@@ -378,7 +381,7 @@
}
final UserHandle userHandle = user.getUserHandle();
- final boolean isSecure = mStorage.hasPassword(userId) || mStorage.hasPattern(userId);
+ final boolean isSecure = isUserSecure(userId);
if (isSecure && !mUserManager.isUserUnlockingOrUnlocked(userHandle)) {
UserInfo parent = mUserManager.getProfileParent(userId);
if (parent != null &&
@@ -453,35 +456,34 @@
}
public void onUnlockUser(final int userId) {
- // Hide notification first, as tie managed profile lock takes time
- hideEncryptionNotification(new UserHandle(userId));
+ // Perform tasks which require locks in LSS on a handler, as we are callbacks from
+ // ActivityManager.unlockUser()
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ // Hide notification first, as tie managed profile lock takes time
+ hideEncryptionNotification(new UserHandle(userId));
- if (mUserManager.getUserInfo(userId).isManagedProfile()) {
- // As tieManagedProfileLockIfNecessary() may try to unlock user, we should not do it
- // in onUnlockUser() synchronously, otherwise it may cause a deadlock
- mHandler.post(new Runnable() {
- @Override
- public void run() {
+ // Now we have unlocked the parent user we should show notifications
+ // about any profiles that exist.
+ List<UserInfo> profiles = mUserManager.getProfiles(userId);
+ for (int i = 0; i < profiles.size(); i++) {
+ UserInfo profile = profiles.get(i);
+ final boolean isSecure = isUserSecure(profile.id);
+ if (isSecure && profile.isManagedProfile()) {
+ UserHandle userHandle = profile.getUserHandle();
+ if (!mUserManager.isUserUnlockingOrUnlocked(userHandle) &&
+ !mUserManager.isQuietModeEnabled(userHandle)) {
+ showEncryptionNotificationForProfile(userHandle);
+ }
+ }
+ }
+
+ if (mUserManager.getUserInfo(userId).isManagedProfile()) {
tieManagedProfileLockIfNecessary(userId, null);
}
- });
- }
-
- // Now we have unlocked the parent user we should show notifications
- // about any profiles that exist.
- List<UserInfo> profiles = mUserManager.getProfiles(userId);
- for (int i = 0; i < profiles.size(); i++) {
- UserInfo profile = profiles.get(i);
- final boolean isSecure =
- mStorage.hasPassword(profile.id) || mStorage.hasPattern(profile.id);
- if (isSecure && profile.isManagedProfile()) {
- UserHandle userHandle = profile.getUserHandle();
- if (!mUserManager.isUserUnlockingOrUnlocked(userHandle) &&
- !mUserManager.isQuietModeEnabled(userHandle)) {
- showEncryptionNotificationForProfile(userHandle);
- }
}
- }
+ });
}
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -809,6 +811,10 @@
return mStorage.hasPattern(userId);
}
+ private boolean isUserSecure(int userId) {
+ return mStorage.hasCredential(userId);
+ }
+
private void setKeystorePassword(String password, int userHandle) {
final KeyStore ks = KeyStore.getInstance();
ks.onUserPasswordChanged(userHandle, password);
@@ -914,21 +920,52 @@
}
}
- private byte[] getCurrentHandle(int userId) {
- CredentialHash credential = mStorage.readCredentialHash(userId);
-
- // sanity check
- if (credential.type != LockPatternUtils.CREDENTIAL_TYPE_NONE && credential.hash == null) {
- Slog.e(TAG, "Stored handle type [" + credential.type + "] but no handle available");
+ private Map<Integer, String> getDecryptedPasswordsForAllTiedProfiles(int userId) {
+ if (mUserManager.getUserInfo(userId).isManagedProfile()) {
+ return null;
}
- return credential.hash;
+ Map<Integer, String> result = new ArrayMap<Integer, String>();
+ final List<UserInfo> profiles = mUserManager.getProfiles(userId);
+ final int size = profiles.size();
+ for (int i = 0; i < size; i++) {
+ final UserInfo profile = profiles.get(i);
+ if (!profile.isManagedProfile()) {
+ continue;
+ }
+ final int managedUserId = profile.id;
+ if (mLockPatternUtils.isSeparateProfileChallengeEnabled(managedUserId)) {
+ continue;
+ }
+ try {
+ result.put(userId, getDecryptedPasswordForTiedProfile(userId));
+ } catch (KeyStoreException | UnrecoverableKeyException | NoSuchAlgorithmException
+ | NoSuchPaddingException | InvalidKeyException
+ | InvalidAlgorithmParameterException | IllegalBlockSizeException
+ | BadPaddingException | CertificateException | IOException e) {
+ // ignore
+ }
+ }
+ return result;
}
- private void onUserLockChanged(int userId) throws RemoteException {
+ /**
+ * Synchronize all profile's work challenge of the given user if it's unified: tie or clear them
+ * depending on the parent user's secure state.
+ *
+ * When clearing tied work challenges, a pre-computed password table for profiles are required,
+ * since changing password for profiles requires existing password, and existing passwords can
+ * only be computed before the parent user's password is cleared.
+ *
+ * Strictly this is a recursive function, since setLockCredentialInternal ends up calling this
+ * method again on profiles. However the recursion is guaranteed to terminate as this method
+ * terminates when the user is a managed profile.
+ */
+ private void synchronizeUnifiedWorkChallengeForProfiles(int userId,
+ Map<Integer, String> profilePasswordMap) throws RemoteException {
if (mUserManager.getUserInfo(userId).isManagedProfile()) {
return;
}
- final boolean isSecure = mStorage.hasPassword(userId) || mStorage.hasPattern(userId);
+ final boolean isSecure = isUserSecure(userId);
final List<UserInfo> profiles = mUserManager.getProfiles(userId);
final int size = profiles.size();
for (int i = 0; i < size; i++) {
@@ -941,11 +978,17 @@
if (isSecure) {
tieManagedProfileLockIfNecessary(managedUserId, null);
} else {
- clearUserKeyProtection(managedUserId);
- getGateKeeperService().clearSecureUserId(managedUserId);
- mStorage.writeCredentialHash(CredentialHash.createEmptyHash(), managedUserId);
- setKeystorePassword(null, managedUserId);
- fixateNewestUserKeyAuth(managedUserId);
+ // We use cached work profile password computed before clearing the parent's
+ // credential, otherwise they get lost
+ if (profilePasswordMap != null && profilePasswordMap.containsKey(managedUserId)) {
+ setLockCredentialInternal(null, LockPatternUtils.CREDENTIAL_TYPE_NONE,
+ profilePasswordMap.get(managedUserId), managedUserId);
+ } else {
+ Slog.wtf(TAG, "clear tied profile challenges, but no password supplied.");
+ // Supplying null here would lead to untrusted credential change
+ setLockCredentialInternal(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, null,
+ managedUserId);
+ }
mStorage.removeChildProfileLock(managedUserId);
removeKeystoreProfileKey(managedUserId);
}
@@ -978,7 +1021,6 @@
private void setLockCredentialInternal(String credential, int credentialType,
String savedCredential, int userId) throws RemoteException {
- byte[] currentHandle = getCurrentHandle(userId);
if (credentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE) {
if (credential != null) {
Slog.wtf(TAG, "CredentialType is none, but credential is non-null.");
@@ -988,27 +1030,31 @@
mStorage.writeCredentialHash(CredentialHash.createEmptyHash(), userId);
setKeystorePassword(null, userId);
fixateNewestUserKeyAuth(userId);
- onUserLockChanged(userId);
+ synchronizeUnifiedWorkChallengeForProfiles(userId, null);
notifyActivePasswordMetricsAvailable(null, userId);
return;
}
if (credential == null) {
throw new RemoteException("Null credential with mismatched credential type");
}
+
+ CredentialHash currentHandle = mStorage.readCredentialHash(userId);
if (isManagedProfileWithUnifiedLock(userId)) {
// get credential from keystore when managed profile has unified lock
- try {
- savedCredential = getDecryptedPasswordForTiedProfile(userId);
- } catch (FileNotFoundException e) {
- Slog.i(TAG, "Child profile key not found");
- } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
- | NoSuchAlgorithmException | NoSuchPaddingException
- | InvalidAlgorithmParameterException | IllegalBlockSizeException
- | BadPaddingException | CertificateException | IOException e) {
- Slog.e(TAG, "Failed to decrypt child profile key", e);
+ if (savedCredential == null) {
+ try {
+ savedCredential = getDecryptedPasswordForTiedProfile(userId);
+ } catch (FileNotFoundException e) {
+ Slog.i(TAG, "Child profile key not found");
+ } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
+ | NoSuchAlgorithmException | NoSuchPaddingException
+ | InvalidAlgorithmParameterException | IllegalBlockSizeException
+ | BadPaddingException | CertificateException | IOException e) {
+ Slog.e(TAG, "Failed to decrypt child profile key", e);
+ }
}
} else {
- if (currentHandle == null) {
+ if (currentHandle.hash == null) {
if (savedCredential != null) {
Slog.w(TAG, "Saved credential provided, but none stored");
}
@@ -1016,17 +1062,19 @@
}
}
- byte[] enrolledHandle = enrollCredential(currentHandle, savedCredential, credential,
+ byte[] enrolledHandle = enrollCredential(currentHandle.hash, savedCredential, credential,
userId);
if (enrolledHandle != null) {
CredentialHash willStore = CredentialHash.create(enrolledHandle, credentialType);
mStorage.writeCredentialHash(willStore, userId);
- // Refresh the auth token
- setUserKeyProtection(userId, credential,
- doVerifyCredential(credential, credentialType, true, 0, userId,
- null /* progressCallback */));
+ // push new secret and auth token to vold
+ GateKeeperResponse gkResponse = getGateKeeperService()
+ .verifyChallenge(userId, 0, willStore.hash, credential.getBytes());
+ setUserKeyProtection(userId, credential, convertResponse(gkResponse));
fixateNewestUserKeyAuth(userId);
- onUserLockChanged(userId);
+ // Refresh the auth token
+ doVerifyCredential(credential, credentialType, true, 0, userId, null /* progressCallback */);
+ synchronizeUnifiedWorkChallengeForProfiles(userId, null);
} else {
throw new RemoteException("Failed to enroll " +
(credentialType == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD ? "password"
@@ -1034,6 +1082,26 @@
}
}
+ private VerifyCredentialResponse convertResponse(GateKeeperResponse gateKeeperResponse) {
+ VerifyCredentialResponse response;
+ int responseCode = gateKeeperResponse.getResponseCode();
+ if (responseCode == GateKeeperResponse.RESPONSE_RETRY) {
+ response = new VerifyCredentialResponse(gateKeeperResponse.getTimeout());
+ } else if (responseCode == GateKeeperResponse.RESPONSE_OK) {
+ byte[] token = gateKeeperResponse.getPayload();
+ if (token == null) {
+ // something's wrong if there's no payload with a challenge
+ Slog.e(TAG, "verifyChallenge response had no associated payload");
+ response = VerifyCredentialResponse.ERROR;
+ } else {
+ response = new VerifyCredentialResponse(token);
+ }
+ } else {
+ response = VerifyCredentialResponse.ERROR;
+ }
+ return response;
+ }
+
@VisibleForTesting
protected void tieProfileLockToParent(int userId, String password) {
if (DEBUG) Slog.v(TAG, "tieProfileLockToParent for user: " + userId);
@@ -1123,6 +1191,7 @@
private void setUserKeyProtection(int userId, String credential, VerifyCredentialResponse vcr)
throws RemoteException {
+ if (DEBUG) Slog.d(TAG, "setUserKeyProtection: user=" + userId);
if (vcr == null) {
throw new RemoteException("Null response verifying a credential we just set");
}
@@ -1138,6 +1207,7 @@
}
private void clearUserKeyProtection(int userId) throws RemoteException {
+ if (DEBUG) Slog.d(TAG, "clearUserKeyProtection user=" + userId);
addUserKeyAuth(userId, null, null);
}
@@ -1171,6 +1241,7 @@
private void fixateNewestUserKeyAuth(int userId)
throws RemoteException {
+ if (DEBUG) Slog.d(TAG, "fixateNewestUserKeyAuth: user=" + userId);
final IStorageManager storageManager = mInjector.getStorageManager();
final long callingId = Binder.clearCallingIdentity();
try {
@@ -1370,27 +1441,10 @@
return VerifyCredentialResponse.ERROR;
}
}
-
- VerifyCredentialResponse response;
- boolean shouldReEnroll = false;
GateKeeperResponse gateKeeperResponse = getGateKeeperService()
.verifyChallenge(userId, challenge, storedHash.hash, credential.getBytes());
- int responseCode = gateKeeperResponse.getResponseCode();
- if (responseCode == GateKeeperResponse.RESPONSE_RETRY) {
- response = new VerifyCredentialResponse(gateKeeperResponse.getTimeout());
- } else if (responseCode == GateKeeperResponse.RESPONSE_OK) {
- byte[] token = gateKeeperResponse.getPayload();
- if (token == null) {
- // something's wrong if there's no payload with a challenge
- Slog.e(TAG, "verifyChallenge response had no associated payload");
- response = VerifyCredentialResponse.ERROR;
- } else {
- shouldReEnroll = gateKeeperResponse.getShouldReEnroll();
- response = new VerifyCredentialResponse(token);
- }
- } else {
- response = VerifyCredentialResponse.ERROR;
- }
+ VerifyCredentialResponse response = convertResponse(gateKeeperResponse);
+ boolean shouldReEnroll = gateKeeperResponse.getShouldReEnroll();
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
diff --git a/services/core/java/com/android/server/LockSettingsShellCommand.java b/services/core/java/com/android/server/LockSettingsShellCommand.java
index e131251..1ab5303 100644
--- a/services/core/java/com/android/server/LockSettingsShellCommand.java
+++ b/services/core/java/com/android/server/LockSettingsShellCommand.java
@@ -116,7 +116,7 @@
}
private void runClear() throws RemoteException {
- mLockPatternUtils.clearLock(mCurrentUserId);
+ mLockPatternUtils.clearLock(mOld, mCurrentUserId);
getOutPrintWriter().println("Lock credential cleared");
}
diff --git a/services/core/java/com/android/server/LockSettingsStorage.java b/services/core/java/com/android/server/LockSettingsStorage.java
index c858036..385b1cf 100644
--- a/services/core/java/com/android/server/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/LockSettingsStorage.java
@@ -290,6 +290,10 @@
hasFile(getLegacyLockPatternFilename(userId));
}
+ public boolean hasCredential(int userId) {
+ return hasPassword(userId) || hasPattern(userId);
+ }
+
private boolean hasFile(String name) {
byte[] contents = readFile(name);
return contents != null && contents.length > 0;
@@ -650,4 +654,5 @@
}
}
}
+
}
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 5fe8b1a..0ac51b9 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -53,6 +53,7 @@
import android.os.IRemoteCallback;
import android.os.Looper;
import android.os.Message;
+import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
@@ -676,6 +677,10 @@
}
}
+ private boolean isCallerSystemProcess(int callingUid) {
+ return callingUid == Process.SYSTEM_UID;
+ }
+
/**
* Obtain the package name of the current active network scorer.
*
@@ -692,6 +697,27 @@
return null;
}
+
+ /**
+ * Returns metadata about the active scorer or <code>null</code> if there is no active scorer.
+ */
+ @Override
+ public NetworkScorerAppData getActiveScorer() {
+ // Only the system can access this data.
+ if (isCallerSystemProcess(getCallingUid()) || callerCanRequestScores()) {
+ synchronized (mServiceConnectionLock) {
+ if (mServiceConnection != null) {
+ return mServiceConnection.mAppData;
+ }
+ }
+ } else {
+ throw new SecurityException(
+ "Caller is neither the system process nor a score requester.");
+ }
+
+ return null;
+ }
+
@Override
public void disableScoring() {
// Only the active scorer or the system should be allowed to disable scoring.
diff --git a/services/core/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java
index 2b5166e..feda273 100644
--- a/services/core/java/com/android/server/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/TextServicesManagerService.java
@@ -20,6 +20,7 @@
import com.android.internal.content.PackageMonitor;
import com.android.internal.inputmethod.InputMethodUtils;
import com.android.internal.textservice.ISpellCheckerService;
+import com.android.internal.textservice.ISpellCheckerServiceCallback;
import com.android.internal.textservice.ISpellCheckerSession;
import com.android.internal.textservice.ISpellCheckerSessionListener;
import com.android.internal.textservice.ITextServicesManager;
@@ -68,7 +69,6 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
-import java.util.concurrent.CopyOnWriteArrayList;
public class TextServicesManagerService extends ITextServicesManager.Stub {
private static final String TAG = TextServicesManagerService.class.getSimpleName();
@@ -549,56 +549,26 @@
return;
}
final SpellCheckerInfo sci = mSpellCheckerMap.get(sciId);
+ SpellCheckerBindGroup bindGroup = mSpellCheckerBindGroups.get(sciId);
final int uid = Binder.getCallingUid();
- if (mSpellCheckerBindGroups.containsKey(sciId)) {
- final SpellCheckerBindGroup bindGroup = mSpellCheckerBindGroups.get(sciId);
- if (bindGroup != null) {
- final InternalDeathRecipient recipient =
- mSpellCheckerBindGroups.get(sciId).addListener(
- tsListener, locale, scListener, uid, bundle);
- if (recipient == null) {
- if (DBG) {
- Slog.w(TAG, "Didn't create a death recipient.");
- }
- return;
- }
- if (bindGroup.mSpellChecker == null & bindGroup.mConnected) {
- Slog.e(TAG, "The state of the spell checker bind group is illegal.");
- bindGroup.removeAll();
- } else if (bindGroup.mSpellChecker != null) {
- if (DBG) {
- Slog.w(TAG, "Existing bind found. Return a spell checker session now. "
- + "Listeners count = " + bindGroup.mListeners.size());
- }
- try {
- final ISpellCheckerSession session =
- bindGroup.mSpellChecker.getISpellCheckerSession(
- recipient.mScLocale, recipient.mScListener, bundle);
- if (session != null) {
- tsListener.onServiceConnected(session);
- return;
- } else {
- if (DBG) {
- Slog.w(TAG, "Existing bind already expired. ");
- }
- bindGroup.removeAll();
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "Exception in getting spell checker session: " + e);
- bindGroup.removeAll();
- }
- }
+ if (bindGroup == null) {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ bindGroup = startSpellCheckerServiceInnerLocked(sci);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ if (bindGroup == null) {
+ // startSpellCheckerServiceInnerLocked failed.
+ return;
}
}
- final long ident = Binder.clearCallingIdentity();
- try {
- startSpellCheckerServiceInnerLocked(
- sci, locale, tsListener, scListener, uid, bundle);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
+
+ // Start getISpellCheckerSession async IPC, or just queue the request until the spell
+ // checker service is bound.
+ bindGroup.getISpellCheckerSessionOrQueueLocked(
+ new SessionRequest(uid, locale, tsListener, scListener, bundle));
}
- return;
}
@Override
@@ -611,9 +581,8 @@
}
}
- private void startSpellCheckerServiceInnerLocked(SpellCheckerInfo info, String locale,
- ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener,
- int uid, Bundle bundle) {
+ @Nullable
+ private SpellCheckerBindGroup startSpellCheckerServiceInnerLocked(SpellCheckerInfo info) {
if (DBG) {
Slog.w(TAG, "Start spell checker session inner locked.");
}
@@ -627,11 +596,11 @@
if (!bindCurrentSpellCheckerService(serviceIntent, connection,
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE)) {
Slog.e(TAG, "Failed to get a spell checker service.");
- return;
+ return null;
}
- final SpellCheckerBindGroup group = new SpellCheckerBindGroup(
- connection, tsListener, locale, scListener, uid, bundle);
+ final SpellCheckerBindGroup group = new SpellCheckerBindGroup(connection);
mSpellCheckerBindGroups.put(sciId, group);
+ return group;
}
@Override
@@ -814,16 +783,32 @@
pw.println(" " + ent.getKey() + " " + grp + ":");
pw.println(" " + "mInternalConnection=" + grp.mInternalConnection);
pw.println(" " + "mSpellChecker=" + grp.mSpellChecker);
- pw.println(" " + "mBound=" + grp.mBound + " mConnected=" + grp.mConnected);
+ pw.println(" " + "mUnbindCalled=" + grp.mUnbindCalled);
+ pw.println(" " + "mConnected=" + grp.mConnected);
+ final int numPendingSessionRequests = grp.mPendingSessionRequests.size();
+ for (int i = 0; i < numPendingSessionRequests; i++) {
+ final SessionRequest req = grp.mPendingSessionRequests.get(i);
+ pw.println(" " + "Pending Request #" + i + ":");
+ pw.println(" " + "mTsListener=" + req.mTsListener);
+ pw.println(" " + "mScListener=" + req.mScListener);
+ pw.println(" " + "mScLocale=" + req.mLocale + " mUid=" + req.mUserId);
+ }
+ final int numOnGoingSessionRequests = grp.mOnGoingSessionRequests.size();
+ for (int i = 0; i < numOnGoingSessionRequests; i++) {
+ final SessionRequest req = grp.mOnGoingSessionRequests.get(i);
+ pw.println(" " + "On going Request #" + i + ":");
+ ++i;
+ pw.println(" " + "mTsListener=" + req.mTsListener);
+ pw.println(" " + "mScListener=" + req.mScListener);
+ pw.println(
+ " " + "mScLocale=" + req.mLocale + " mUid=" + req.mUserId);
+ }
final int N = grp.mListeners.size();
for (int i = 0; i < N; i++) {
final InternalDeathRecipient listener = grp.mListeners.get(i);
pw.println(" " + "Listener #" + i + ":");
- pw.println(" " + "mTsListener=" + listener.mTsListener);
pw.println(" " + "mScListener=" + listener.mScListener);
pw.println(" " + "mGroup=" + listener.mGroup);
- pw.println(" " + "mScLocale=" + listener.mScLocale
- + " mUid=" + listener.mUid);
}
}
pw.println("");
@@ -832,25 +817,44 @@
}
}
+ private static final class SessionRequest {
+ @UserIdInt
+ public final int mUserId;
+ @Nullable
+ public final String mLocale;
+ @NonNull
+ public final ITextServicesSessionListener mTsListener;
+ @NonNull
+ public final ISpellCheckerSessionListener mScListener;
+ @Nullable
+ public final Bundle mBundle;
+
+ SessionRequest(@UserIdInt final int userId, @Nullable String locale,
+ @NonNull ITextServicesSessionListener tsListener,
+ @NonNull ISpellCheckerSessionListener scListener, @Nullable Bundle bundle) {
+ mUserId = userId;
+ mLocale = locale;
+ mTsListener = tsListener;
+ mScListener = scListener;
+ mBundle = bundle;
+ }
+ }
+
// SpellCheckerBindGroup contains active text service session listeners.
// If there are no listeners anymore, the SpellCheckerBindGroup instance will be removed from
// mSpellCheckerBindGroups
private final class SpellCheckerBindGroup {
private final String TAG = SpellCheckerBindGroup.class.getSimpleName();
private final InternalServiceConnection mInternalConnection;
- private final CopyOnWriteArrayList<InternalDeathRecipient> mListeners =
- new CopyOnWriteArrayList<>();
- public boolean mBound;
- public ISpellCheckerService mSpellChecker;
- public boolean mConnected;
+ private final ArrayList<InternalDeathRecipient> mListeners = new ArrayList<>();
+ private boolean mUnbindCalled;
+ private ISpellCheckerService mSpellChecker;
+ private boolean mConnected;
+ private final ArrayList<SessionRequest> mPendingSessionRequests = new ArrayList<>();
+ private final ArrayList<SessionRequest> mOnGoingSessionRequests = new ArrayList<>();
- public SpellCheckerBindGroup(InternalServiceConnection connection,
- ITextServicesSessionListener listener, String locale,
- ISpellCheckerSessionListener scListener, int uid, Bundle bundle) {
+ public SpellCheckerBindGroup(InternalServiceConnection connection) {
mInternalConnection = connection;
- mBound = true;
- mConnected = false;
- addListener(listener, locale, scListener, uid, bundle);
}
public void onServiceConnected(ISpellCheckerService spellChecker) {
@@ -858,55 +862,15 @@
Slog.d(TAG, "onServiceConnected");
}
- for (InternalDeathRecipient listener : mListeners) {
- try {
- final ISpellCheckerSession session = spellChecker.getISpellCheckerSession(
- listener.mScLocale, listener.mScListener, listener.mBundle);
- synchronized(mSpellCheckerMap) {
- if (mListeners.contains(listener)) {
- listener.mTsListener.onServiceConnected(session);
- }
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "Exception in getting the spell checker session."
- + "Reconnect to the spellchecker. ", e);
- removeAll();
- return;
- }
- }
synchronized(mSpellCheckerMap) {
mSpellChecker = spellChecker;
mConnected = true;
+ // Dispatch pending getISpellCheckerSession requests.
+ mPendingSessionRequests.forEach(this::getISpellCheckerSessionLocked);
+ mPendingSessionRequests.clear();
}
}
- public InternalDeathRecipient addListener(ITextServicesSessionListener tsListener,
- String locale, ISpellCheckerSessionListener scListener, int uid, Bundle bundle) {
- if (DBG) {
- Slog.d(TAG, "addListener: " + locale);
- }
- InternalDeathRecipient recipient = null;
- synchronized(mSpellCheckerMap) {
- try {
- final int size = mListeners.size();
- for (int i = 0; i < size; ++i) {
- if (mListeners.get(i).hasSpellCheckerListener(scListener)) {
- // do not add the lister if the group already contains this.
- return null;
- }
- }
- recipient = new InternalDeathRecipient(
- this, tsListener, locale, scListener, uid, bundle);
- scListener.asBinder().linkToDeath(recipient, 0);
- mListeners.add(recipient);
- } catch(RemoteException e) {
- // do nothing
- }
- cleanLocked();
- }
- return recipient;
- }
-
public void removeListener(ISpellCheckerSessionListener listener) {
if (DBG) {
Slog.w(TAG, "remove listener: " + listener.hashCode());
@@ -941,20 +905,29 @@
if (DBG) {
Slog.d(TAG, "cleanLocked");
}
- // If there are no more active listeners, clean up. Only do this
- // once.
- if (mBound && mListeners.isEmpty()) {
- mBound = false;
- final String sciId = mInternalConnection.mSciId;
- SpellCheckerBindGroup cur = mSpellCheckerBindGroups.get(sciId);
- if (cur == this) {
- if (DBG) {
- Slog.d(TAG, "Remove bind group.");
- }
- mSpellCheckerBindGroups.remove(sciId);
- }
- mContext.unbindService(mInternalConnection);
+ if (mUnbindCalled) {
+ return;
}
+ // If there are no more active listeners, clean up. Only do this once.
+ if (!mListeners.isEmpty()) {
+ return;
+ }
+ if (!mPendingSessionRequests.isEmpty()) {
+ return;
+ }
+ if (!mOnGoingSessionRequests.isEmpty()) {
+ return;
+ }
+ final String sciId = mInternalConnection.mSciId;
+ final SpellCheckerBindGroup cur = mSpellCheckerBindGroups.get(sciId);
+ if (cur == this) {
+ if (DBG) {
+ Slog.d(TAG, "Remove bind group.");
+ }
+ mSpellCheckerBindGroups.remove(sciId);
+ }
+ mContext.unbindService(mInternalConnection);
+ mUnbindCalled = true;
}
public void removeAll() {
@@ -966,6 +939,59 @@
idr.mScListener.asBinder().unlinkToDeath(idr, 0);
}
mListeners.clear();
+ mPendingSessionRequests.clear();
+ mOnGoingSessionRequests.clear();
+ cleanLocked();
+ }
+ }
+
+ public void getISpellCheckerSessionOrQueueLocked(@NonNull SessionRequest request) {
+ if (mUnbindCalled) {
+ return;
+ }
+ if (!mConnected) {
+ mPendingSessionRequests.add(request);
+ return;
+ }
+ getISpellCheckerSessionLocked(request);
+ }
+
+ private void getISpellCheckerSessionLocked(@NonNull SessionRequest request) {
+ if (mUnbindCalled) {
+ return;
+ }
+ try {
+ mSpellChecker.getISpellCheckerSession(
+ request.mLocale, request.mScListener, request.mBundle,
+ new ISpellCheckerServiceCallbackBinder(this, request));
+ mOnGoingSessionRequests.add(request);
+ } catch(RemoteException e) {
+ // The target spell checker service is not available. Better to reset the state.
+ removeAll();
+ }
+ cleanLocked();
+ }
+
+ void onSessionCreated(@Nullable final ISpellCheckerSession newSession,
+ @NonNull final SessionRequest request) {
+ synchronized (mSpellCheckerMap) {
+ if (mUnbindCalled) {
+ return;
+ }
+ if (mOnGoingSessionRequests.remove(request)) {
+ final InternalDeathRecipient recipient =
+ new InternalDeathRecipient(this, request.mScListener);
+ try {
+ request.mTsListener.onServiceConnected(newSession);
+ request.mScListener.asBinder().linkToDeath(recipient, 0);
+ mListeners.add(recipient);
+ } catch (RemoteException e) {
+ // Technically this can happen if the spell checker client app is already
+ // dead. We can just forget about this request; the request is already
+ // removed from mOnGoingSessionRequests and the death recipient listener is
+ // not yet added to mListeners. There is nothing to release further.
+ }
+ }
cleanLocked();
}
}
@@ -1008,21 +1034,13 @@
}
private static final class InternalDeathRecipient implements IBinder.DeathRecipient {
- public final ITextServicesSessionListener mTsListener;
public final ISpellCheckerSessionListener mScListener;
- public final String mScLocale;
private final SpellCheckerBindGroup mGroup;
- public final int mUid;
- public final Bundle mBundle;
+
public InternalDeathRecipient(SpellCheckerBindGroup group,
- ITextServicesSessionListener tsListener, String scLocale,
- ISpellCheckerSessionListener scListener, int uid, Bundle bundle) {
- mTsListener = tsListener;
+ ISpellCheckerSessionListener scListener) {
mScListener = scListener;
- mScLocale = scLocale;
mGroup = group;
- mUid = uid;
- mBundle = bundle;
}
public boolean hasSpellCheckerListener(ISpellCheckerSessionListener listener) {
@@ -1035,6 +1053,25 @@
}
}
+ private static final class ISpellCheckerServiceCallbackBinder
+ extends ISpellCheckerServiceCallback.Stub {
+ @NonNull
+ private final SpellCheckerBindGroup mBindGroup;
+ @NonNull
+ private final SessionRequest mRequest;
+
+ ISpellCheckerServiceCallbackBinder(@NonNull final SpellCheckerBindGroup bindGroup,
+ @NonNull final SessionRequest request) {
+ mBindGroup = bindGroup;
+ mRequest = request;
+ }
+
+ @Override
+ public void onSessionCreated(@Nullable ISpellCheckerSession newSession) {
+ mBindGroup.onSessionCreated(newSession, mRequest);
+ }
+ }
+
private static final class TextServicesSettings {
private final ContentResolver mResolver;
@UserIdInt
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 6f2f2c4..acacb9e 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -772,7 +772,8 @@
}
private void registerVrStateListener() {
- IVrManager vrManager = IVrManager.Stub.asInterface(ServiceManager.getService("vrmanager"));
+ IVrManager vrManager = IVrManager.Stub.asInterface(ServiceManager.getService(
+ Context.VR_SERVICE));
try {
if (vrManager != null) {
vrManager.registerListener(mVrStateCallbacks);
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index fdd7cb1..fbc4440 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -636,11 +636,10 @@
return visibility;
}
- if (isPermittedForPackage(packageName, accounts.userId,
- Manifest.permission.GET_ACCOUNTS_PRIVILEGED)) {
- return AccountManager.VISIBILITY_VISIBLE;
- }
- // Profile owner gets visibility by default.
+ boolean isPrivileged = isPermittedForPackage(packageName, accounts.userId,
+ Manifest.permission.GET_ACCOUNTS_PRIVILEGED);
+
+ // Device/Profile owner gets visibility by default.
if (isProfileOwner(uid)) {
return AccountManager.VISIBILITY_VISIBLE;
}
@@ -650,7 +649,7 @@
boolean preO = isPreOApplication(packageName);
if ((signatureCheckResult != SIGNATURE_CHECK_MISMATCH)
|| (preO && checkGetAccountsPermission(packageName, accounts.userId))
- || canReadContacts) {
+ || canReadContacts || isPrivileged) {
// Use legacy for preO apps with GET_ACCOUNTS permission or pre/postO with signature
// match.
visibility = getAccountVisibility(account,
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 3c90f93..100d821 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -36,7 +36,7 @@
private static final String KEY_MAX_CACHED_PROCESSES = "max_cached_processes";
private static final boolean DEFAULT_ENFORCE_BG_CHECK = SystemProperties.getBoolean(
- "debug.bgcheck", false);
+ "debug.bgcheck", true);
private static final int DEFAULT_MAX_CACHED_PROCESSES = 32;
// Enforce background check on apps targeting O?
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 93fb911..3ab4e6d 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2611,6 +2611,14 @@
mPermissionReviewRequired = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_permissionReviewRequired);
+ mHandlerThread = new ServiceThread(TAG,
+ android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
+ mHandlerThread.start();
+ mHandler = new MainHandler(mHandlerThread.getLooper());
+ mUiHandler = new UiHandler();
+
+ mConstants = new ActivityManagerConstants(this, mHandler);
+
if (DEBUG_BACKGROUND_CHECK) {
Slog.d(TAG, "Enforcing O+ bg restrictions: " + mConstants.ENFORCE_BG_CHECK);
StringBuilder sb = new StringBuilder(200);
@@ -2622,14 +2630,6 @@
Slog.d(TAG, sb.toString());
}
- mHandlerThread = new ServiceThread(TAG,
- android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
- mHandlerThread.start();
- mHandler = new MainHandler(mHandlerThread.getLooper());
- mUiHandler = new UiHandler();
-
- mConstants = new ActivityManagerConstants(this, mHandler);
-
/* static; one-time init here */
if (sKillHandler == null) {
sKillThread = new ServiceThread(TAG + ":kill",
@@ -5326,7 +5326,8 @@
for (int pid : pids) {
if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for native pid " + pid);
final long sime = SystemClock.elapsedRealtime();
- Debug.dumpNativeBacktraceToFile(pid, tracesPath);
+
+ Debug.dumpNativeBacktraceToFileTimeout(pid, tracesPath, 10);
if (DEBUG_ANR) Slog.d(TAG, "Done with native pid " + pid
+ " in " + (SystemClock.elapsedRealtime()-sime) + "ms");
}
@@ -5563,7 +5564,7 @@
// Reset notification settings.
INotificationManager inm = NotificationManager.getService();
- inm.clearData(packageName, pkgUidF);
+ inm.clearData(packageName, pkgUidF, uid == pkgUidF);
} catch (RemoteException e) {
}
} finally {
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index a1c5653..b4feef3 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -49,11 +49,18 @@
* that they lost focus.
*/
static final boolean ENFORCE_DUCKING = false;
+ /**
+ * set to true so the framework enforces muting media/game itself when the device is ringing
+ * or in a call.
+ */
+ static final boolean ENFORCE_MUTING_FOR_RING_OR_CALL = true;
private final Context mContext;
private final AppOpsManager mAppOps;
private PlayerFocusEnforcer mFocusEnforcer; // never null
+ private boolean mRingOrCallActive = false;
+
protected MediaFocusControl(Context cntxt, PlayerFocusEnforcer pfe) {
mContext = cntxt;
mAppOps = (AppOpsManager)mContext.getSystemService(Context.APP_OPS_SERVICE);
@@ -78,6 +85,16 @@
mFocusEnforcer.unduckPlayers(winner);
}
+ @Override
+ public void mutePlayersForCall(int[] usagesToMute) {
+ mFocusEnforcer.mutePlayersForCall(usagesToMute);
+ }
+
+ @Override
+ public void unmutePlayersForCall() {
+ mFocusEnforcer.unmutePlayersForCall();
+ }
+
//==========================================================================================
// AudioFocus
//==========================================================================================
@@ -139,7 +156,9 @@
stackIterator.next().dump(pw);
}
}
- pw.println("\n Notify on duck: " + mNotifyFocusOwnerOnDuck +"\n");
+ pw.println("\n");
+ pw.println(" Notify on duck: " + mNotifyFocusOwnerOnDuck + "\n");
+ pw.println(" In ring or call: " + mRingOrCallActive + "\n");
}
/**
@@ -401,6 +420,18 @@
}
/**
+ * Delay after entering ringing or call mode after which the framework will mute streams
+ * that are still playing.
+ */
+ private static final int RING_CALL_MUTING_ENFORCEMENT_DELAY_MS = 100;
+
+ /**
+ * Usages to mute when the device rings or is in a call
+ */
+ private final static int[] USAGES_TO_MUTE_IN_RING_OR_CALL =
+ { AudioAttributes.USAGE_MEDIA, AudioAttributes.USAGE_GAME };
+
+ /**
* Return the volume ramp time expected before playback with the given AudioAttributes would
* start after gaining audio focus.
* @param attr attributes of the sound about to start playing
@@ -452,6 +483,10 @@
}
synchronized(mAudioFocusLock) {
+ boolean enteringRingOrCall = !mRingOrCallActive
+ & (AudioSystem.IN_VOICE_COMM_FOCUS_ID.compareTo(clientId) == 0);
+ if (enteringRingOrCall) { mRingOrCallActive = true; }
+
boolean focusGrantDelayed = false;
if (!canReassignAudioFocus()) {
if ((flags & AudioManager.AUDIOFOCUS_FLAG_DELAY_OK) == 0) {
@@ -523,6 +558,9 @@
notifyExtPolicyFocusGrant_syncAf(nfr.toAudioFocusInfo(),
AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
+ if (ENFORCE_MUTING_FOR_RING_OR_CALL & enteringRingOrCall) {
+ runAudioCheckerForRingOrCallAsync(true/*enteringRingOrCall*/);
+ }
}//synchronized(mAudioFocusLock)
return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
@@ -539,7 +577,15 @@
try {
// this will take care of notifying the new focus owner if needed
synchronized(mAudioFocusLock) {
+ boolean exitingRingOrCall = mRingOrCallActive
+ & (AudioSystem.IN_VOICE_COMM_FOCUS_ID.compareTo(clientId) == 0);
+ if (exitingRingOrCall) { mRingOrCallActive = false; }
+
removeFocusStackEntry(clientId, true /*signal*/, true /*notifyFocusFollowers*/);
+
+ if (ENFORCE_MUTING_FOR_RING_OR_CALL & exitingRingOrCall) {
+ runAudioCheckerForRingOrCallAsync(false/*enteringRingOrCall*/);
+ }
}
} catch (java.util.ConcurrentModificationException cme) {
// Catching this exception here is temporary. It is here just to prevent
@@ -559,4 +605,26 @@
}
}
+ private void runAudioCheckerForRingOrCallAsync(final boolean enteringRingOrCall) {
+ new Thread() {
+ public void run() {
+ if (enteringRingOrCall) {
+ try {
+ Thread.sleep(RING_CALL_MUTING_ENFORCEMENT_DELAY_MS);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ synchronized (mAudioFocusLock) {
+ // since the new thread starting running the state could have changed, so
+ // we need to check again mRingOrCallActive, not enteringRingOrCall
+ if (mRingOrCallActive) {
+ mFocusEnforcer.mutePlayersForCall(USAGES_TO_MUTE_IN_RING_OR_CALL);
+ } else {
+ mFocusEnforcer.unmutePlayersForCall();
+ }
+ }
+ }
+ }.start();
+ }
}
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index 4930c53..3f8bbe5 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -147,6 +147,11 @@
for (int piid : mDuckedPlayers) {
pw.println(" " + piid);
}
+ // players muted due to the device ringing or being in a call
+ pw.println("\n muted player piids:");
+ for (int piid : mMutedPlayers) {
+ pw.println(" " + piid);
+ }
}
}
@@ -231,6 +236,7 @@
//=================================================================
// PlayerFocusEnforcer implementation
private final ArrayList<Integer> mDuckedPlayers = new ArrayList<Integer>();
+ private final ArrayList<Integer> mMutedPlayers = new ArrayList<Integer>();
@Override
public boolean duckPlayers(FocusRequester winner, FocusRequester loser) {
@@ -290,9 +296,9 @@
&& winner.hasSameUid(apc.getClientUid())) {
try {
if (DEBUG) { Log.v(TAG, "unducking player" + piid); }
+ mDuckedPlayers.remove(new Integer(piid));
//FIXME just a test before we have VolumeShape
apc.getPlayerProxy().setPan(0.0f);
- mDuckedPlayers.remove(new Integer(piid));
} catch (Exception e) {
Log.e(TAG, "Error unducking player " + piid, e);
}
@@ -303,6 +309,65 @@
}
}
+ @Override
+ public void mutePlayersForCall(int[] usagesToMute) {
+ if (DEBUG) {
+ String log = new String("mutePlayersForCall: usages=");
+ for (int usage : usagesToMute) { log += " " + usage; }
+ Log.v(TAG, log);
+ }
+ synchronized (mPlayerLock) {
+ final Set<Integer> piidSet = mPlayers.keySet();
+ final Iterator<Integer> piidIterator = piidSet.iterator();
+ // find which players to mute
+ while (piidIterator.hasNext()) {
+ final Integer piid = piidIterator.next();
+ final AudioPlaybackConfiguration apc = mPlayers.get(piid);
+ final int playerUsage = apc.getAudioAttributes().getUsage();
+ boolean mute = false;
+ for (int usageToMute : usagesToMute) {
+ if (playerUsage == usageToMute) {
+ mute = true;
+ break;
+ }
+ }
+ if (mute) {
+ try {
+ if (DEBUG) { Log.v(TAG, "muting player" + piid); }
+ apc.getPlayerProxy().setVolume(0.0f);
+ mMutedPlayers.add(piid);
+ } catch (Exception e) {
+ Log.e(TAG, "Error muting player " + piid, e);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void unmutePlayersForCall() {
+ if (DEBUG) {
+ Log.v(TAG, "unmutePlayersForCall()");
+ }
+ synchronized (mPlayerLock) {
+ if (mMutedPlayers.isEmpty()) {
+ return;
+ }
+ for (int piid : mMutedPlayers) {
+ final AudioPlaybackConfiguration apc = mPlayers.get(piid);
+ if (apc != null) {
+ try {
+ if (DEBUG) { Log.v(TAG, "unmuting player" + piid); }
+ apc.getPlayerProxy().setVolume(1.0f);
+ mMutedPlayers.remove(new Integer(piid));
+ } catch (Exception e) {
+ Log.e(TAG, "Error unmuting player " + piid, e);
+ }
+ }
+ }
+ }
+ }
+
//=================================================================
// Track playback activity listeners
diff --git a/services/core/java/com/android/server/audio/PlayerFocusEnforcer.java b/services/core/java/com/android/server/audio/PlayerFocusEnforcer.java
index acb4f0d..0733eca 100644
--- a/services/core/java/com/android/server/audio/PlayerFocusEnforcer.java
+++ b/services/core/java/com/android/server/audio/PlayerFocusEnforcer.java
@@ -28,4 +28,8 @@
public boolean duckPlayers(FocusRequester winner, FocusRequester loser);
public void unduckPlayers(FocusRequester winner);
+
+ public void mutePlayersForCall(int[] usagesToMute);
+
+ public void unmutePlayersForCall();
}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/display/NightDisplayService.java b/services/core/java/com/android/server/display/NightDisplayService.java
index 7237fdb..cba694c 100644
--- a/services/core/java/com/android/server/display/NightDisplayService.java
+++ b/services/core/java/com/android/server/display/NightDisplayService.java
@@ -141,8 +141,7 @@
@Override
public void onBootPhase(int phase) {
if (phase == PHASE_SYSTEM_SERVICES_READY) {
- IVrManager vrManager =
- (IVrManager) getBinderService(VrManagerService.VR_MANAGER_BINDER_SERVICE);
+ IVrManager vrManager = (IVrManager) getBinderService(Context.VR_SERVICE);
if (vrManager != null) {
try {
vrManager.registerListener(mVrStateCallbacks);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index 4a10f50..07c3a38 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -25,7 +25,6 @@
import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.util.IndentingPrintWriter;
-import com.android.internal.util.Predicate;
import com.android.server.hdmi.HdmiAnnotations.IoThreadOnly;
import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
import com.android.server.hdmi.HdmiControlService.DevicePollingCallback;
@@ -34,6 +33,7 @@
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
+import java.util.function.Predicate;
import java.util.concurrent.ArrayBlockingQueue;
import libcore.util.EmptyArray;
import sun.util.locale.LanguageTag;
@@ -77,7 +77,7 @@
// Predicate for whether the given logical address is remote device's one or not.
private final Predicate<Integer> mRemoteDeviceAddressPredicate = new Predicate<Integer>() {
@Override
- public boolean apply(Integer address) {
+ public boolean test(Integer address) {
return !isAllocatedLocalDeviceAddress(address);
}
};
@@ -85,7 +85,7 @@
// Predicate whether the given logical address is system audio's one or not
private final Predicate<Integer> mSystemAudioAddressPredicate = new Predicate<Integer>() {
@Override
- public boolean apply(Integer address) {
+ public boolean test(Integer address) {
return HdmiUtils.getTypeFromAddress(address) == Constants.ADDR_AUDIO_SYSTEM;
}
};
@@ -427,7 +427,7 @@
switch (iterationStrategy) {
case Constants.POLL_ITERATION_IN_ORDER:
for (int i = Constants.ADDR_TV; i <= Constants.ADDR_SPECIFIC_USE; ++i) {
- if (pickPredicate.apply(i)) {
+ if (pickPredicate.test(i)) {
pollingCandidates.add(i);
}
}
@@ -435,7 +435,7 @@
case Constants.POLL_ITERATION_REVERSE_ORDER:
default: // The default is reverse order.
for (int i = Constants.ADDR_SPECIFIC_USE; i >= Constants.ADDR_TV; --i) {
- if (pickPredicate.apply(i)) {
+ if (pickPredicate.test(i)) {
pollingCandidates.add(i);
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index b543b73..cc3fc00 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -115,6 +115,9 @@
import android.service.notification.NotificationAssistantService;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationRankingUpdate;
+import android.service.notification.NotificationRecordProto;
+import android.service.notification.NotificationServiceDumpProto;
+import android.service.notification.NotificationServiceProto;
import android.service.notification.SnoozeCriterion;
import android.service.notification.StatusBarNotification;
import android.service.notification.ZenModeConfig;
@@ -128,6 +131,7 @@
import android.util.Slog;
import android.util.SparseArray;
import android.util.Xml;
+import android.util.proto.ProtoOutputStream;
import android.view.WindowManagerInternal;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
@@ -1694,7 +1698,7 @@
@Override
- public void clearData(String packageName, int uid) throws RemoteException {
+ public void clearData(String packageName, int uid, boolean fromApp) throws RemoteException {
checkCallerIsSystem();
// Cancel posted notifications
@@ -1709,8 +1713,10 @@
mConditionProviders.onPackagesChanged(true, new String[] {packageName});
// Reset notification preferences
- mRankingHelper.onPackagesChanged(true, UserHandle.getCallingUserId(),
- new String[] {packageName}, new int[] {uid});
+ if (!fromApp) {
+ mRankingHelper.onPackagesChanged(true, UserHandle.getCallingUserId(),
+ new String[]{packageName}, new int[]{uid});
+ }
savePolicyFile();
}
@@ -2400,6 +2406,8 @@
final DumpFilter filter = DumpFilter.parseFromArguments(args);
if (filter != null && filter.stats) {
dumpJson(pw, filter);
+ } else if (filter != null && filter.proto) {
+ dumpProto(fd, filter);
} else {
dumpImpl(pw, filter);
}
@@ -2764,6 +2772,33 @@
pw.println(dump);
}
+ private void dumpProto(FileDescriptor fd, DumpFilter filter) {
+ final ProtoOutputStream proto = new ProtoOutputStream(fd);
+ synchronized (mNotificationLock) {
+ long records = proto.start(NotificationServiceDumpProto.RECORDS);
+ int N = mNotificationList.size();
+ if (N > 0) {
+ for (int i = 0; i < N; i++) {
+ final NotificationRecord nr = mNotificationList.get(i);
+ if (filter.filtered && !filter.matches(nr.sbn)) continue;
+ nr.dump(proto, filter.redact);
+ proto.write(NotificationRecordProto.STATE, NotificationServiceProto.POSTED);
+ }
+ }
+ N = mEnqueuedNotifications.size();
+ if (N > 0) {
+ for (int i = 0; i < N; i++) {
+ final NotificationRecord nr = mEnqueuedNotifications.get(i);
+ if (filter.filtered && !filter.matches(nr.sbn)) continue;
+ nr.dump(proto, filter.redact);
+ proto.write(NotificationRecordProto.STATE, NotificationServiceProto.ENQUEUED);
+ }
+ }
+ proto.end(records);
+ }
+ proto.flush();
+ }
+
void dumpImpl(PrintWriter pw, DumpFilter filter) {
pw.print("Current Notification Manager state");
if (filter.filtered) {
@@ -4822,11 +4857,15 @@
public long since;
public boolean stats;
public boolean redact = true;
+ public boolean proto = false;
public static DumpFilter parseFromArguments(String[] args) {
final DumpFilter filter = new DumpFilter();
for (int ai = 0; ai < args.length; ai++) {
final String a = args[ai];
+ if ("--proto".equals(args[0])) {
+ filter.proto = true;
+ }
if ("--noredact".equals(a) || "--reveal".equals(a)) {
filter.redact = false;
} else if ("p".equals(a) || "pkg".equals(a) || "--package".equals(a)) {
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index d26aa9e..3016b17 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -37,12 +37,14 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.service.notification.NotificationListenerService;
+import android.service.notification.NotificationRecordProto;
import android.service.notification.SnoozeCriterion;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
@@ -185,7 +187,9 @@
int defaultLightOff = mContext.getResources().getInteger(
com.android.internal.R.integer.config_defaultNotificationLedOff);
- Light light = getChannel().shouldShowLights() ? new Light(defaultLightColor,
+ int channelLightColor = getChannel().getLightColor() != 0 ? getChannel().getLightColor()
+ : defaultLightColor;
+ Light light = getChannel().shouldShowLights() ? new Light(channelLightColor,
defaultLightOn, defaultLightOff) : null;
if (mPreChannelsNotification
&& (getChannel().getUserLockedFields()
@@ -335,6 +339,24 @@
/** @deprecated Use {@link #getUser()} instead. */
public int getUserId() { return sbn.getUserId(); }
+ void dump(ProtoOutputStream proto, boolean redact) {
+ proto.write(NotificationRecordProto.KEY, sbn.getKey());
+ if (getChannel() != null) {
+ proto.write(NotificationRecordProto.CHANNEL_ID, getChannel().getId());
+ }
+ proto.write(NotificationRecordProto.CAN_SHOW_LIGHT, getLight() != null);
+ proto.write(NotificationRecordProto.CAN_VIBRATE, getVibration() != null);
+ proto.write(NotificationRecordProto.FLAGS, sbn.getNotification().flags);
+ proto.write(NotificationRecordProto.GROUP_KEY, getGroupKey());
+ proto.write(NotificationRecordProto.IMPORTANCE, getImportance());
+ if (getSound() != null) {
+ proto.write(NotificationRecordProto.SOUND, getSound().toString());
+ }
+ if (getAudioAttributes() != null) {
+ proto.write(NotificationRecordProto.SOUND_USAGE, getAudioAttributes().getUsage());
+ }
+ }
+
void dump(PrintWriter pw, String prefix, Context baseContext, boolean redact) {
final Notification notification = sbn.getNotification();
final Icon icon = notification.getSmallIcon();
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 8176e5d..46c449b 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -563,7 +563,8 @@
channel.setImportance(updatedChannel.getImportance());
}
if ((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_LIGHTS) == 0) {
- channel.setLights(updatedChannel.shouldShowLights());
+ channel.enableLights(updatedChannel.shouldShowLights());
+ channel.setLightColor(updatedChannel.getLightColor());
}
if ((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_PRIORITY) == 0) {
channel.setBypassDnd(updatedChannel.canBypassDnd());
@@ -673,7 +674,7 @@
public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroups(String pkg,
int uid, boolean includeDeleted) {
Preconditions.checkNotNull(pkg);
- List<NotificationChannelGroup> groups = new ArrayList<>();
+ Map<String, NotificationChannelGroup> groups = new ArrayMap<>();
Record r = getRecord(pkg, uid);
if (r == null) {
return ParceledListSlice.emptyList();
@@ -684,23 +685,21 @@
final NotificationChannel nc = r.channels.valueAt(i);
if (includeDeleted || !nc.isDeleted()) {
if (nc.getGroup() != null) {
- // lazily populate channel list
- NotificationChannelGroup ncg = r.groups.get(nc.getGroup());
+ NotificationChannelGroup ncg = groups.get(nc.getGroup());
+ if (ncg == null ) {
+ ncg = r.groups.get(nc.getGroup()).clone();
+ groups.put(nc.getGroup(), ncg);
+ }
ncg.addChannel(nc);
} else {
nonGrouped.addChannel(nc);
}
}
}
- for (NotificationChannelGroup group : r.groups.values()) {
- if (group.getChannels().size() > 0) {
- groups.add(group);
- }
- }
if (nonGrouped.getChannels().size() > 0) {
- groups.add(nonGrouped);
+ groups.put(null, nonGrouped);
}
- return new ParceledListSlice<>(groups);
+ return new ParceledListSlice<>(new ArrayList<>(groups.values()));
}
@Override
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 66977d6..7aa96cf 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -252,7 +252,7 @@
return result;
}
- if (SystemProperties.getBoolean("dalvik.vm.deopt.secondary", false)) {
+ if (SystemProperties.getBoolean("dalvik.vm.dexopt.secondary", false)) {
result = reconcileSecondaryDexFiles(pm.getDexManager());
if (result == OPTIMIZE_ABORT_BY_JOB_SCHEDULER) {
return result;
diff --git a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
index 9bf0476..364bf28 100644
--- a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
+++ b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
@@ -125,7 +125,7 @@
void systemReady() {
IVrManager vrManager = IVrManager.Stub.asInterface(
- ServiceManager.getService(VrManagerService.VR_MANAGER_BINDER_SERVICE));
+ ServiceManager.getService(Context.VR_SERVICE));
if (vrManager != null) {
try {
vrManager.registerListener(mVrStateCallbacks);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index c795676..3e05157 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -149,6 +149,7 @@
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiPlaybackClient;
import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback;
+import android.hardware.input.InputManager;
import android.hardware.input.InputManagerInternal;
import android.hardware.power.V1_0.PowerHint;
import android.media.AudioAttributes;
@@ -203,6 +204,7 @@
import android.view.KeyCharacterMap.FallbackAction;
import android.view.KeyEvent;
import android.view.MotionEvent;
+import android.view.PointerIcon;
import android.view.Surface;
import android.view.View;
import android.view.ViewConfiguration;
@@ -4246,6 +4248,9 @@
mInputConsumer = mWindowManagerFuncs.createInputConsumer(mHandler.getLooper(),
INPUT_CONSUMER_NAVIGATION,
(channel, looper) -> new HideNavInputEventReceiver(channel, looper));
+ // As long as mInputConsumer is active, hover events are not dispatched to the app
+ // and the pointer icon is likely to become stale. Hide it to avoid confusion.
+ InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_NULL);
}
// For purposes of positioning and showing the nav bar, if we have
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 91a5f4f..ffbb428 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -732,8 +732,7 @@
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.DOUBLE_TAP_TO_WAKE),
false, mSettingsObserver, UserHandle.USER_ALL);
- IVrManager vrManager =
- (IVrManager) getBinderService(VrManagerService.VR_MANAGER_BINDER_SERVICE);
+ IVrManager vrManager = (IVrManager) getBinderService(Context.VR_SERVICE);
if (vrManager != null) {
try {
vrManager.registerListener(mVrStateCallbacks);
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 51c4ce31..69a9f80 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -89,8 +89,6 @@
public static final String TAG = "VrManagerService";
- public static final String VR_MANAGER_BINDER_SERVICE = "vrmanager";
-
private static final int PENDING_STATE_DELAY_MS = 300;
private static final int EVENT_LOG_SIZE = 32;
private static final int INVALID_APPOPS_MODE = -1;
@@ -377,7 +375,7 @@
@Override
public void setPersistentVrModeEnabled(boolean enabled) {
- enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
+ enforceCallerPermission(Manifest.permission.RESTRICTED_VR_ACCESS);
VrManagerService.this.setPersistentVrModeEnabled(enabled);
}
@@ -487,7 +485,7 @@
}
publishLocalService(VrManagerInternal.class, new LocalService());
- publishBinderService(VR_MANAGER_BINDER_SERVICE, mVrManager.asBinder());
+ publishBinderService(Context.VR_SERVICE, mVrManager.asBinder());
}
@Override
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 061aa83..2263042 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -173,10 +173,9 @@
boolean showForAllUsers, int targetSdk, int orientation, int rotationAnimationHint,
int configChanges, boolean launchTaskBehind, boolean alwaysFocusable,
AppWindowContainerController controller) {
- this(service, token, voiceInteraction, dc);
+ this(service, token, voiceInteraction, dc, fullscreen);
setController(controller);
mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
- mFillsParent = fullscreen;
mShowForAllUsers = showForAllUsers;
mTargetSdk = targetSdk;
mOrientation = orientation;
@@ -191,11 +190,12 @@
}
AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction,
- DisplayContent dc) {
+ DisplayContent dc, boolean fillsParent) {
super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc,
false /* ownerCanManageAppTokens */);
appToken = token;
mVoiceInteraction = voiceInteraction;
+ mFillsParent = fillsParent;
mInputApplicationHandle = new InputApplicationHandle(this);
mAppAnimator = new AppWindowAnimator(this, service);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 003b6d0..5075a41 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1887,7 +1887,10 @@
private void setDeviceOwnerSystemPropertyLocked() {
// Device owner may still be provisioned, do not set the read-only system property yet.
- if (mInjector.settingsGlobalGetInt(Settings.Global.DEVICE_PROVISIONED, 0) == 0) {
+ // Wear devices don't set device_provisioned until the device is paired, so allow
+ // device_owner property to be set without that.
+ if (!mIsWatch
+ && mInjector.settingsGlobalGetInt(Settings.Global.DEVICE_PROVISIONED, 0) == 0) {
return;
}
// Still at the first stage of CryptKeeper double bounce, mOwners.hasDeviceOwner is
@@ -4297,7 +4300,7 @@
if (!TextUtils.isEmpty(password)) {
mLockPatternUtils.saveLockPassword(password, null, quality, userHandle);
} else {
- mLockPatternUtils.clearLock(userHandle);
+ mLockPatternUtils.clearLock(null, userHandle);
}
boolean requireEntry = (flags & DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY) != 0;
if (requireEntry) {
diff --git a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 9202cce..15f7557 100644
--- a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -20,7 +20,6 @@
import static junit.framework.Assert.assertTrue;
import com.android.server.lights.Light;
-import com.android.server.statusbar.StatusBarManagerInternal;
import org.junit.Before;
import org.junit.Test;
@@ -224,7 +223,7 @@
} else {
builder.setLights(CUSTOM_LIGHT_COLOR, CUSTOM_LIGHT_ON, CUSTOM_LIGHT_OFF);
}
- channel.setLights(true);
+ channel.enableLights(true);
}
builder.setDefaults(defaults);
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
index 0ec368f..13d6c5d 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
@@ -33,6 +33,7 @@
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.graphics.Color;
import android.media.AudioAttributes;
import android.net.Uri;
import android.os.Build;
@@ -137,10 +138,11 @@
defaults |= Notification.DEFAULT_LIGHTS;
} else {
builder.setLights(CUSTOM_LIGHT.color, CUSTOM_LIGHT.onMs, CUSTOM_LIGHT.offMs);
+ channel.setLightColor(Color.BLUE);
}
- channel.setLights(true);
+ channel.enableLights(true);
} else {
- channel.setLights(false);
+ channel.enableLights(false);
}
builder.setDefaults(defaults);
@@ -316,7 +318,7 @@
@Test
public void testLights_locked_preUpgrade() throws Exception {
- defaultChannel.setLights(true);
+ defaultChannel.enableLights(true);
defaultChannel.lockFields(NotificationChannel.USER_LOCKED_LIGHTS);
StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
@@ -327,7 +329,7 @@
}
@Test
- public void testLights_upgrade() throws Exception {
+ public void testLights_upgrade_defaultLights() throws Exception {
int defaultLightColor = mMockContext.getResources().getColor(
com.android.internal.R.color.config_defaultNotificationColor);
int defaultLightOn = mMockContext.getResources().getInteger(
@@ -339,6 +341,22 @@
defaultLightColor, defaultLightOn, defaultLightOff);
StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+ true /* lights */, true /*defaultLights */);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+ assertEquals(expected, record.getLight());
+ }
+
+ @Test
+ public void testLights_upgrade() throws Exception {
+ int defaultLightOn = mMockContext.getResources().getInteger(
+ com.android.internal.R.integer.config_defaultNotificationLedOn);
+ int defaultLightOff = mMockContext.getResources().getInteger(
+ com.android.internal.R.integer.config_defaultNotificationLedOff);
+
+ NotificationRecord.Light expected = new NotificationRecord.Light(
+ Color.BLUE, defaultLightOn, defaultLightOff);
+ StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
true /* lights */, false /*defaultLights */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
assertEquals(expected, record.getLight());
diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
index 9fa46d1..9ea9ce9 100644
--- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
@@ -15,6 +15,8 @@
*/
package com.android.server.notification;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.fail;
@@ -36,6 +38,7 @@
import android.app.NotificationManager;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.graphics.Color;
import android.media.AudioAttributes;
import android.net.Uri;
import android.os.Build;
@@ -55,6 +58,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -167,7 +171,7 @@
private NotificationChannel getDefaultChannel() {
return new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "name",
- NotificationManager.IMPORTANCE_LOW);
+ IMPORTANCE_LOW);
}
private ByteArrayOutputStream writeXmlAndPurge(String pkg, int uid, String... channelIds)
@@ -200,6 +204,7 @@
assertTrue(Arrays.equals(expected.getVibrationPattern(), actual.getVibrationPattern()));
assertEquals(expected.getGroup(), actual.getGroup());
assertEquals(expected.getAudioAttributes(), actual.getAudioAttributes());
+ assertEquals(expected.getLightColor(), actual.getLightColor());
}
@Test
@@ -258,14 +263,15 @@
NotificationChannel channel1 =
new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
NotificationChannel channel2 =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel2.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
- channel2.setLights(true);
+ channel2.enableLights(true);
channel2.setBypassDnd(true);
channel2.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
channel2.enableVibration(true);
channel2.setGroup(ncg.getId());
channel2.setVibrationPattern(new long[]{100, 67, 145, 156});
+ channel2.setLightColor(Color.BLUE);
mHelper.createNotificationChannelGroup(pkg, uid, ncg, true);
mHelper.createNotificationChannel(pkg, uid, channel1, true);
@@ -291,10 +297,26 @@
mHelper.getNotificationChannel(pkg, uid, channel2.getId(), false));
assertNotNull(mHelper.getNotificationChannel(
pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID, false));
- assertEquals(ncg.getId(),
- mHelper.getNotificationChannelGroups(pkg, uid, false).getList().get(0).getId());
- assertEquals(channel2.getGroup(), mHelper.getNotificationChannelGroups(
- pkg, uid, false).getList().get(0).getChannels().get(0).getGroup());
+
+ List<NotificationChannelGroup> actualGroups =
+ mHelper.getNotificationChannelGroups(pkg, uid, false).getList();
+ boolean foundNcg = false;
+ for (NotificationChannelGroup actual : actualGroups) {
+ if (ncg.getId().equals(actual.getId())) {
+ foundNcg = true;
+ break;
+ }
+ }
+ assertTrue(foundNcg);
+
+ boolean foundChannel2Group = false;
+ for (NotificationChannelGroup actual : actualGroups) {
+ if (channel2.getGroup().equals(actual.getChannels().get(0).getGroup())) {
+ foundChannel2Group = true;
+ break;
+ }
+ }
+ assertTrue(foundChannel2Group);
}
@Test
@@ -329,7 +351,7 @@
final NotificationChannel defaultChannel = mHelper.getNotificationChannel(
pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID, false);
- defaultChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+ defaultChannel.setImportance(IMPORTANCE_LOW);
mHelper.updateNotificationChannel(pkg, uid, defaultChannel);
ByteArrayOutputStream baos = writeXmlAndPurge(pkg, uid, channel1.getId(),
@@ -341,7 +363,7 @@
parser.nextTag();
mHelper.readXml(parser, false);
- assertEquals(NotificationManager.IMPORTANCE_LOW, mHelper.getNotificationChannel(
+ assertEquals(IMPORTANCE_LOW, mHelper.getNotificationChannel(
pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID, false).getImportance());
}
@@ -373,7 +395,7 @@
final NotificationChannel updated2 = mHelper.getNotificationChannel(
pkg2, uid2, NotificationChannel.DEFAULT_CHANNEL_ID, false);
// clamped
- assertEquals(NotificationManager.IMPORTANCE_LOW, updated2.getImportance());
+ assertEquals(IMPORTANCE_LOW, updated2.getImportance());
assertFalse(updated2.canBypassDnd());
assertEquals(Notification.VISIBILITY_PRIVATE, updated2.getLockscreenVisibility());
assertEquals(NotificationChannel.USER_LOCKED_VISIBILITY, updated2.getUserLockedFields());
@@ -385,7 +407,7 @@
try {
mHelper.createNotificationChannel(pkg, uid,
- new NotificationChannel(pkg, "", NotificationManager.IMPORTANCE_LOW), true);
+ new NotificationChannel(pkg, "", IMPORTANCE_LOW), true);
fail("Channel creation should fail");
} catch (IllegalArgumentException e) {
// pass
@@ -396,7 +418,7 @@
public void testUpdate_userLockedImportance() throws Exception {
// all fields locked by user
final NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
mHelper.createNotificationChannel(pkg, uid, channel, false);
@@ -415,7 +437,7 @@
public void testUpdate_userLockedVisibility() throws Exception {
// all fields locked by user
final NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
channel.lockFields(NotificationChannel.USER_LOCKED_VISIBILITY);
@@ -436,8 +458,8 @@
public void testUpdate_userLockedVibration() throws Exception {
// all fields locked by user
final NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
- channel.setLights(false);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
+ channel.enableLights(false);
channel.lockFields(NotificationChannel.USER_LOCKED_VIBRATION);
mHelper.createNotificationChannel(pkg, uid, channel, false);
@@ -458,8 +480,8 @@
public void testUpdate_userLockedLights() throws Exception {
// all fields locked by user
final NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
- channel.setLights(false);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
+ channel.enableLights(false);
channel.lockFields(NotificationChannel.USER_LOCKED_LIGHTS);
mHelper.createNotificationChannel(pkg, uid, channel, false);
@@ -467,7 +489,7 @@
// same id, try to update
final NotificationChannel channel2 =
new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
- channel2.setLights(true);
+ channel2.enableLights(true);
mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2);
@@ -479,7 +501,7 @@
public void testUpdate_userLockedPriority() throws Exception {
// all fields locked by user
final NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel.setBypassDnd(true);
channel.lockFields(NotificationChannel.USER_LOCKED_PRIORITY);
@@ -500,7 +522,7 @@
public void testUpdate_userLockedRingtone() throws Exception {
// all fields locked by user
final NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
channel.lockFields(NotificationChannel.USER_LOCKED_SOUND);
@@ -520,7 +542,7 @@
@Test
public void testUpdate_userLockedBadge() throws Exception {
final NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel.setShowBadge(true);
channel.lockFields(NotificationChannel.USER_LOCKED_SHOW_BADGE);
@@ -540,9 +562,9 @@
public void testUpdate() throws Exception {
// no fields locked by user
final NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
- channel.setLights(true);
+ channel.enableLights(true);
channel.setBypassDnd(true);
channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
@@ -552,7 +574,7 @@
final NotificationChannel channel2 =
new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
channel2.setSound(new Uri.Builder().scheme("test2").build(), mAudioAttributes);
- channel2.setLights(false);
+ channel2.enableLights(false);
channel2.setBypassDnd(false);
channel2.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
@@ -572,9 +594,9 @@
@Test
public void testCreateChannel_CannotChangeHiddenFields() throws Exception {
final NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
- channel.setLights(true);
+ channel.enableLights(true);
channel.setBypassDnd(true);
channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
channel.setShowBadge(true);
@@ -599,9 +621,9 @@
@Test
public void testCreateChannel_CannotChangeHiddenFieldsAssistant() throws Exception {
final NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
- channel.setLights(true);
+ channel.enableLights(true);
channel.setBypassDnd(true);
channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
channel.setShowBadge(true);
@@ -626,9 +648,9 @@
@Test
public void testGetDeletedChannel() throws Exception {
NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
- channel.setLights(true);
+ channel.enableLights(true);
channel.setBypassDnd(true);
channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
channel.enableVibration(true);
@@ -652,9 +674,9 @@
public void testGetDeletedChannels() throws Exception {
Map<String, NotificationChannel> channelMap = new HashMap<>();
NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
- channel.setLights(true);
+ channel.enableLights(true);
channel.setBypassDnd(true);
channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
channel.enableVibration(true);
@@ -691,7 +713,7 @@
@Test
public void testUpdateDeletedChannels() throws Exception {
NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
mHelper.createNotificationChannel(pkg, uid, channel, true);
mHelper.deleteNotificationChannel(pkg, uid, channel.getId());
@@ -716,7 +738,7 @@
public void testCreateDeletedChannel() throws Exception {
long[] vibration = new long[]{100, 67, 145, 156};
NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel.setVibrationPattern(vibration);
mHelper.createNotificationChannel(pkg, uid, channel, true);
@@ -737,7 +759,7 @@
public void testCreateChannel_alreadyExists() throws Exception {
long[] vibration = new long[]{100, 67, 145, 156};
NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel.setVibrationPattern(vibration);
mHelper.createNotificationChannel(pkg, uid, channel, true);
@@ -758,7 +780,7 @@
NotificationChannel channel1 =
new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
NotificationChannel channel2 =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
mHelper.createNotificationChannel(pkg, uid, channel1, true);
mHelper.createNotificationChannel(pkg, uid, channel2, false);
@@ -897,4 +919,29 @@
}
}
}
+
+ @Test
+ public void testGetChannelGroups_noSideEffects() throws Exception {
+ NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
+ mHelper.createNotificationChannelGroup(pkg, uid, ncg, true);
+
+ NotificationChannel channel1 =
+ new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
+ channel1.setGroup(ncg.getId());
+ mHelper.createNotificationChannel(pkg, uid, channel1, true);
+ mHelper.getNotificationChannelGroups(pkg, uid, true).getList();
+
+ channel1.setImportance(IMPORTANCE_LOW);
+ mHelper.updateNotificationChannel(pkg, uid, channel1);
+
+ List<NotificationChannelGroup> actual =
+ mHelper.getNotificationChannelGroups(pkg, uid, true).getList();
+
+ assertEquals(2, actual.size());
+ for (NotificationChannelGroup group : actual) {
+ if (Objects.equals(group.getId(),ncg.getId())) {
+ assertEquals(1, group.getChannels().size());
+ }
+ }
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/LockSettingsShellCommandTest.java b/services/tests/servicestests/src/com/android/server/LockSettingsShellCommandTest.java
index d6ee367..84ebb19 100644
--- a/services/tests/servicestests/src/com/android/server/LockSettingsShellCommandTest.java
+++ b/services/tests/servicestests/src/com/android/server/LockSettingsShellCommandTest.java
@@ -137,6 +137,6 @@
assertEquals(0, mCommand.exec(new Binder(), in, out, err,
new String[] { "clear", "--old", "1234" },
mShellCallback, mResultReceiver));
- verify(mLockPatternUtils).clearLock(mUserId);
+ verify(mLockPatternUtils).clearLock("1234", mUserId);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
index fa9e9a8..3a88e9c 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
@@ -829,6 +829,50 @@
assertEquals(expectedList, actualList);
}
+ @Test
+ public void testGetActiveScorer_notConnected_canRequestScores() throws Exception {
+ when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
+ .thenReturn(PackageManager.PERMISSION_GRANTED);
+ assertNull(mNetworkScoreService.getActiveScorer());
+ }
+
+ @Test
+ public void testGetActiveScorer_notConnected_canNotRequestScores() throws Exception {
+ when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
+ .thenReturn(PackageManager.PERMISSION_DENIED);
+ try {
+ mNetworkScoreService.getActiveScorer();
+ fail("SecurityException expected.");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testGetActiveScorer_connected_canRequestScores()
+ throws Exception {
+ when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
+ .thenReturn(PackageManager.PERMISSION_GRANTED);
+ NetworkScorerAppData expectedAppData =
+ new NetworkScorerAppData(Binder.getCallingUid(), RECOMMENDATION_SERVICE_COMP);
+ bindToScorer(expectedAppData);
+ assertEquals(expectedAppData, mNetworkScoreService.getActiveScorer());
+ }
+
+ @Test
+ public void testGetActiveScorer_connected_canNotRequestScores()
+ throws Exception {
+ when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
+ .thenReturn(PackageManager.PERMISSION_DENIED);
+ bindToScorer(false);
+ try {
+ mNetworkScoreService.getActiveScorer();
+ fail("SecurityException expected.");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
// "injects" the mock INetworkRecommendationProvider into the NetworkScoreService.
private void injectProvider() {
when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
@@ -849,9 +893,13 @@
}
private void bindToScorer(boolean callerIsScorer) {
- final int callingUid = callerIsScorer ? Binder.getCallingUid() : 0;
+ final int callingUid = callerIsScorer ? Binder.getCallingUid() : Binder.getCallingUid() + 1;
NetworkScorerAppData appData =
new NetworkScorerAppData(callingUid, RECOMMENDATION_SERVICE_COMP);
+ bindToScorer(appData);
+ }
+
+ private void bindToScorer(NetworkScorerAppData appData) {
when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(appData);
when(mContext.bindServiceAsUser(isA(Intent.class), isA(ServiceConnection.class), anyInt(),
isA(UserHandle.class))).thenReturn(true);
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
index 154fa91..e15d40e 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import org.junit.Test;
+import org.junit.Ignore;
import org.junit.runner.RunWith;
import android.platform.test.annotations.Presubmit;
@@ -70,6 +71,7 @@
// The base application window should be below all other windows.
assertEquals(baseWin, token.getFirstChild());
+ token.removeImmediately();
}
@Test
@@ -86,6 +88,7 @@
assertEquals(window1, token.findMainWindow());
final WindowState window2 = createWindow(null, TYPE_APPLICATION_STARTING, token, "window2");
assertEquals(window2, token.findMainWindow());
+ token.removeImmediately();
}
@Test
@@ -123,6 +126,8 @@
}
@Test
+ @Ignore
+ // TODO(b/35034729): Need to fix before re-enabling
public void testLandscapeSeascapeRotationByPolicy() throws Exception {
// Some plumbing to get the service ready for rotation updates.
sWm.mDisplayReady = true;
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java
index 1260a53..e6975e7 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -77,6 +78,7 @@
* as does some basic tests (e.g. dragging in Y only will keep X stable).
*/
@Test
+ @Ignore
public void testBasicFreeWindowResizing() throws Exception {
final Rect r = new Rect(100, 220, 700, 520);
final int midY = (r.top + r.bottom) / 2;
@@ -137,6 +139,7 @@
* This tests that by dragging any edge, the fixed / opposite edge(s) remains anchored.
*/
@Test
+ @Ignore
public void testFreeWindowResizingTestAllEdges() throws Exception {
final Rect r = new Rect(100, 220, 700, 520);
final int midX = (r.left + r.right) / 2;
@@ -221,6 +224,7 @@
* right things upon resizing when dragged from the top left corner.
*/
@Test
+ @Ignore
public void testLandscapePreservedWindowResizingDragTopLeft() throws Exception {
final Rect r = new Rect(100, 220, 700, 520);
@@ -258,6 +262,7 @@
* right things upon resizing when dragged from the left corner.
*/
@Test
+ @Ignore
public void testLandscapePreservedWindowResizingDragLeft() throws Exception {
final Rect r = new Rect(100, 220, 700, 520);
final int midY = (r.top + r.bottom) / 2;
@@ -298,6 +303,7 @@
* right things upon resizing when dragged from the top corner.
*/
@Test
+ @Ignore
public void testLandscapePreservedWindowResizingDragTop() throws Exception {
final Rect r = new Rect(100, 220, 700, 520);
final int midX = (r.left + r.right) / 2;
@@ -334,6 +340,7 @@
* right things upon resizing when dragged from the top left corner.
*/
@Test
+ @Ignore
public void testPortraitPreservedWindowResizingDragTopLeft() throws Exception {
final Rect r = new Rect(330, 100, 630, 600);
@@ -366,6 +373,7 @@
* right things upon resizing when dragged from the left corner.
*/
@Test
+ @Ignore
public void testPortraitPreservedWindowResizingDragLeft() throws Exception {
final Rect r = new Rect(330, 100, 630, 600);
final int midY = (r.top + r.bottom) / 2;
@@ -408,6 +416,7 @@
* right things upon resizing when dragged from the top corner.
*/
@Test
+ @Ignore
public void testPortraitPreservedWindowResizingDragTop() throws Exception {
final Rect r = new Rect(330, 100, 630, 600);
final int midX = (r.left + r.right) / 2;
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 1e471e3..dd45d9b 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -18,8 +18,12 @@
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doAnswer;
+import org.mockito.invocation.InvocationOnMock;
import android.annotation.Nullable;
+import android.app.ActivityManagerInternal;
import android.content.Context;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
@@ -64,6 +68,19 @@
LocalServices.addService(PowerManagerInternal.class,
mock(PowerManagerInternal.class));
}
+ if (LocalServices.getService(ActivityManagerInternal.class) == null) {
+ LocalServices.addService(ActivityManagerInternal.class,
+ mock(ActivityManagerInternal.class));
+ final ActivityManagerInternal am =
+ LocalServices.getService(ActivityManagerInternal.class);
+ doAnswer((InvocationOnMock invocationOnMock) -> {
+ final Runnable runnable = invocationOnMock.getArgumentAt(0, Runnable.class);
+ if (runnable != null) {
+ runnable.run();
+ }
+ return null;
+ }).when(am).notifyKeyguardFlagsChanged(any());
+ }
sWm = WindowManagerService.main(context, mock(InputManagerService.class), true, false,
false, new TestWindowManagerPolicy());
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
index 772bfb4..cf8af67 100644
--- a/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
@@ -17,25 +17,14 @@
package com.android.server.wm;
import static junit.framework.Assert.assertTrue;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.doAnswer;
-import android.app.ActivityManagerInternal;
-import android.content.Context;
import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import com.android.server.LocalServices;
-
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.invocation.InvocationOnMock;
/**
* Test class for {@link AppTransition}.
@@ -52,64 +41,50 @@
@Before
public void setUp() throws Exception {
super.setUp();
- final Context context = InstrumentationRegistry.getTargetContext();
- doAnswer((InvocationOnMock invocationOnMock) -> {
- invocationOnMock.getArgumentAt(0, Runnable.class).run();
- return null;
- }).when(sMockAm).notifyKeyguardFlagsChanged(any());
- mWm = TestWindowManagerPolicy.getWindowManagerService(context);
- }
-
- @After
- public void tearDown() throws Exception {
- LocalServices.removeServiceForTest(ActivityManagerInternal.class);
+ sWm.mUnknownAppVisibilityController.clear();
}
@Test
public void testFlow() throws Exception {
- AppWindowToken token = createAppToken();
- mWm.mUnknownAppVisibilityController.notifyLaunched(token);
- mWm.mUnknownAppVisibilityController.notifyAppResumedFinished(token);
- mWm.mUnknownAppVisibilityController.notifyRelayouted(token);
+ final AppWindowToken token = new TestAppWindowToken(sDisplayContent);
+ sWm.mUnknownAppVisibilityController.notifyLaunched(token);
+ sWm.mUnknownAppVisibilityController.notifyAppResumedFinished(token);
+ sWm.mUnknownAppVisibilityController.notifyRelayouted(token);
// Make sure our handler processed the message.
Thread.sleep(100);
- assertTrue(mWm.mUnknownAppVisibilityController.allResolved());
+ assertTrue(sWm.mUnknownAppVisibilityController.allResolved());
}
@Test
public void testMultiple() throws Exception {
- AppWindowToken token1 = createAppToken();
- AppWindowToken token2 = createAppToken();
- mWm.mUnknownAppVisibilityController.notifyLaunched(token1);
- mWm.mUnknownAppVisibilityController.notifyAppResumedFinished(token1);
- mWm.mUnknownAppVisibilityController.notifyLaunched(token2);
- mWm.mUnknownAppVisibilityController.notifyRelayouted(token1);
- mWm.mUnknownAppVisibilityController.notifyAppResumedFinished(token2);
- mWm.mUnknownAppVisibilityController.notifyRelayouted(token2);
+ final AppWindowToken token1 = new TestAppWindowToken(sDisplayContent);
+ final AppWindowToken token2 = new TestAppWindowToken(sDisplayContent);
+ sWm.mUnknownAppVisibilityController.notifyLaunched(token1);
+ sWm.mUnknownAppVisibilityController.notifyAppResumedFinished(token1);
+ sWm.mUnknownAppVisibilityController.notifyLaunched(token2);
+ sWm.mUnknownAppVisibilityController.notifyRelayouted(token1);
+ sWm.mUnknownAppVisibilityController.notifyAppResumedFinished(token2);
+ sWm.mUnknownAppVisibilityController.notifyRelayouted(token2);
// Make sure our handler processed the message.
Thread.sleep(100);
- assertTrue(mWm.mUnknownAppVisibilityController.allResolved());
+ assertTrue(sWm.mUnknownAppVisibilityController.allResolved());
}
@Test
public void testClear() throws Exception {
- AppWindowToken token = createAppToken();
- mWm.mUnknownAppVisibilityController.notifyLaunched(token);
- mWm.mUnknownAppVisibilityController.clear();;
- assertTrue(mWm.mUnknownAppVisibilityController.allResolved());
+ final AppWindowToken token = new TestAppWindowToken(sDisplayContent);
+ sWm.mUnknownAppVisibilityController.notifyLaunched(token);
+ sWm.mUnknownAppVisibilityController.clear();;
+ assertTrue(sWm.mUnknownAppVisibilityController.allResolved());
}
@Test
public void testAppRemoved() throws Exception {
- AppWindowToken token = createAppToken();
- mWm.mUnknownAppVisibilityController.notifyLaunched(token);
- mWm.mUnknownAppVisibilityController.appRemoved(token);
- assertTrue(mWm.mUnknownAppVisibilityController.allResolved());
- }
-
- private AppWindowToken createAppToken() {
- return new AppWindowToken(mWm, null, false, mWm.getDefaultDisplayContentLocked());
+ final AppWindowToken token = new TestAppWindowToken(sDisplayContent);
+ sWm.mUnknownAppVisibilityController.notifyLaunched(token);
+ sWm.mUnknownAppVisibilityController.appRemoved(token);
+ assertTrue(sWm.mUnknownAppVisibilityController.allResolved());
}
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
index 4f9cd95..74557e2 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
@@ -392,7 +392,7 @@
testGetOrientation_childSpecifiedConfig(false, SCREEN_ORIENTATION_LANDSCAPE,
SCREEN_ORIENTATION_LANDSCAPE);
testGetOrientation_childSpecifiedConfig(false, SCREEN_ORIENTATION_UNSET,
- SCREEN_ORIENTATION_UNSET);
+ SCREEN_ORIENTATION_UNSPECIFIED);
}
private void testGetOrientation_childSpecifiedConfig(boolean childVisible, int childOrientation,
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowLayersControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowLayersControllerTests.java
index c8650bf..b99b8fe 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowLayersControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowLayersControllerTests.java
@@ -135,8 +135,9 @@
@Test
public void testAssignWindowLayers_ForImeNonAppImeTarget() throws Exception {
- final WindowState imeSystemOverlayTarget =
- createWindow(null, TYPE_SYSTEM_OVERLAY, sDisplayContent, "imeSystemOverlayTarget");
+ final WindowState imeSystemOverlayTarget = createWindow(null, TYPE_SYSTEM_OVERLAY,
+ sDisplayContent, "imeSystemOverlayTarget",
+ true /* ownerCanAddInternalSystemWindow */);
sWm.mInputMethodTarget = imeSystemOverlayTarget;
sLayersController.assignWindowLayers(sDisplayContent);
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index bc85017..8a94b83 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -17,7 +17,6 @@
package com.android.server.wm;
import android.app.ActivityManager.TaskDescription;
-import android.app.ActivityManagerInternal;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.hardware.display.DisplayManagerGlobal;
@@ -26,9 +25,8 @@
import android.view.DisplayInfo;
import android.view.IApplicationToken;
import org.junit.Assert;
+import org.junit.After;
import org.junit.Before;
-import org.mockito.Mock;
-import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import android.app.ActivityManager.TaskSnapshot;
@@ -59,7 +57,8 @@
import static org.mockito.Mockito.mock;
import com.android.server.AttributeCache;
-import com.android.server.LocalServices;
+
+import java.util.HashSet;
/**
* Common base class for window manager unit test classes.
@@ -86,18 +85,16 @@
static WindowState sAppWindow;
static WindowState sChildAppWindowAbove;
static WindowState sChildAppWindowBelow;
- static @Mock ActivityManagerInternal sMockAm;
+ static HashSet<WindowState> sCommonWindows;
@Before
public void setUp() throws Exception {
if (sOneTimeSetupDone) {
- Mockito.reset(sMockAm);
return;
}
sOneTimeSetupDone = true;
MockitoAnnotations.initMocks(this);
final Context context = InstrumentationRegistry.getTargetContext();
- LocalServices.addService(ActivityManagerInternal.class, sMockAm);
AttributeCache.init(context);
sWm = TestWindowManagerPolicy.getWindowManagerService(context);
sPolicy = (TestWindowManagerPolicy) sWm.mPolicy;
@@ -119,20 +116,33 @@
sWm.mDisplayReady = true;
// Set-up some common windows.
- sWallpaperWindow = createWindow(null, TYPE_WALLPAPER, sDisplayContent, "wallpaperWindow");
- sImeWindow = createWindow(null, TYPE_INPUT_METHOD, sDisplayContent, "sImeWindow");
- sImeDialogWindow =
- createWindow(null, TYPE_INPUT_METHOD_DIALOG, sDisplayContent, "sImeDialogWindow");
- sStatusBarWindow = createWindow(null, TYPE_STATUS_BAR, sDisplayContent, "sStatusBarWindow");
- sNavBarWindow =
- createWindow(null, TYPE_NAVIGATION_BAR, sDisplayContent, "sNavBarWindow");
- sDockedDividerWindow =
- createWindow(null, TYPE_DOCK_DIVIDER, sDisplayContent, "sDockedDividerWindow");
- sAppWindow = createWindow(null, TYPE_BASE_APPLICATION, sDisplayContent, "sAppWindow");
- sChildAppWindowAbove = createWindow(sAppWindow,
- TYPE_APPLICATION_ATTACHED_DIALOG, sAppWindow.mToken, "sChildAppWindowAbove");
- sChildAppWindowBelow = createWindow(sAppWindow,
- TYPE_APPLICATION_MEDIA_OVERLAY, sAppWindow.mToken, "sChildAppWindowBelow");
+ sCommonWindows = new HashSet();
+ sWallpaperWindow = createCommonWindow(null, TYPE_WALLPAPER, "wallpaperWindow");
+ sImeWindow = createCommonWindow(null, TYPE_INPUT_METHOD, "sImeWindow");
+ sImeDialogWindow = createCommonWindow(null, TYPE_INPUT_METHOD_DIALOG, "sImeDialogWindow");
+ sStatusBarWindow = createCommonWindow(null, TYPE_STATUS_BAR, "sStatusBarWindow");
+ sNavBarWindow = createCommonWindow(null, TYPE_NAVIGATION_BAR, "sNavBarWindow");
+ sDockedDividerWindow = createCommonWindow(null, TYPE_DOCK_DIVIDER, "sDockedDividerWindow");
+ sAppWindow = createCommonWindow(null, TYPE_BASE_APPLICATION, "sAppWindow");
+ sChildAppWindowAbove = createCommonWindow(sAppWindow, TYPE_APPLICATION_ATTACHED_DIALOG,
+ "sChildAppWindowAbove");
+ sChildAppWindowBelow = createCommonWindow(sAppWindow, TYPE_APPLICATION_MEDIA_OVERLAY,
+ "sChildAppWindowBelow");
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ sWm.mRoot.forAllWindows(w -> {
+ if (!sCommonWindows.contains(w)) {
+ w.removeImmediately();
+ }
+ }, true /* traverseTopToBottom */);
+ }
+
+ private static WindowState createCommonWindow(WindowState parent, int type, String name) {
+ final WindowState win = createWindow(parent, type, name);
+ sCommonWindows.add(win);
+ return win;
}
/** Asserts that the first entry is greater than the second entry. */
@@ -176,12 +186,23 @@
return createWindow(parent, type, token, name);
}
+ static WindowState createWindow(WindowState parent, int type, DisplayContent dc, String name,
+ boolean ownerCanAddInternalSystemWindow) {
+ final WindowToken token = createWindowToken(dc, type);
+ return createWindow(parent, type, token, name, ownerCanAddInternalSystemWindow);
+ }
+
static WindowState createWindow(WindowState parent, int type, WindowToken token, String name) {
+ return createWindow(parent, type, token, name, false /* ownerCanAddInternalSystemWindow */);
+ }
+
+ static WindowState createWindow(WindowState parent, int type, WindowToken token, String name,
+ boolean ownerCanAddInternalSystemWindow) {
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(type);
attrs.setTitle(name);
final WindowState w = new WindowState(sWm, sMockSession, sIWindow, token, parent, OP_NONE,
- 0, attrs, 0, 0, false /* ownerCanAddInternalSystemWindow */);
+ 0, attrs, 0, 0, ownerCanAddInternalSystemWindow);
// TODO: Probably better to make this call in the WindowState ctor to avoid errors with
// adding it to the token...
token.addWindow(w);
@@ -240,7 +261,7 @@
static class TestAppWindowToken extends AppWindowToken {
TestAppWindowToken(DisplayContent dc) {
- super(sWm, null, false, dc);
+ super(sWm, null, false, dc, true /* fillsParent */);
}
TestAppWindowToken(WindowManagerService service, IApplicationToken token,
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 6ca0bc5..d9465dc 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -259,4 +259,9 @@
* @see TelecomServiceImpl#isOutgoingCallPermitted
*/
boolean isOutgoingCallPermitted(in PhoneAccountHandle phoneAccountHandle);
+
+ /**
+ * @see TelecomServiceImpl#waitOnHandler
+ */
+ void waitOnHandlers();
}
diff --git a/core/java/com/android/internal/util/Predicate.java b/test-runner/src/com/android/internal/util/Predicate.java
similarity index 100%
rename from core/java/com/android/internal/util/Predicate.java
rename to test-runner/src/com/android/internal/util/Predicate.java
diff --git a/core/java/com/android/internal/util/Predicates.java b/test-runner/src/com/android/internal/util/Predicates.java
similarity index 99%
rename from core/java/com/android/internal/util/Predicates.java
rename to test-runner/src/com/android/internal/util/Predicates.java
index c006564..30b8dc6 100644
--- a/core/java/com/android/internal/util/Predicates.java
+++ b/test-runner/src/com/android/internal/util/Predicates.java
@@ -21,6 +21,7 @@
/**
* Predicates contains static methods for creating the standard set of
* {@code Predicate} objects.
+ * @hide
*/
public class Predicates {
diff --git a/core/tests/utiltests/src/com/android/internal/util/PredicatesTest.java b/test-runner/tests/src/com/android/internal/util/PredicatesTest.java
similarity index 100%
rename from core/tests/utiltests/src/com/android/internal/util/PredicatesTest.java
rename to test-runner/tests/src/com/android/internal/util/PredicatesTest.java
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
index 5767f11..0401737 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
@@ -172,12 +172,10 @@
@Override
public void onHandleAssist(Bundle data, AssistStructure structure, AssistContent content) {
mAssistStructure = structure;
- if (mAssistStructure != null) {
- if (mAssistVisualizer != null) {
+ if (mAssistVisualizer != null) {
+ if (mAssistStructure != null) {
mAssistVisualizer.setAssistStructure(mAssistStructure);
- }
- } else {
- if (mAssistVisualizer != null) {
+ } else {
mAssistVisualizer.clearAssistData();
}
}
@@ -207,19 +205,24 @@
@Override
public void onHandleScreenshot(Bitmap screenshot) {
- if (screenshot != null) {
- mScreenshot.setImageBitmap(screenshot);
- mScreenshot.setAdjustViewBounds(true);
- mScreenshot.setMaxWidth(screenshot.getWidth() / 3);
- mScreenshot.setMaxHeight(screenshot.getHeight() / 3);
- mFullScreenshot.setImageBitmap(screenshot);
- } else {
- mScreenshot.setImageDrawable(null);
- mFullScreenshot.setImageDrawable(null);
+ if (mScreenshot != null) {
+ if (screenshot != null) {
+ mScreenshot.setImageBitmap(screenshot);
+ mScreenshot.setAdjustViewBounds(true);
+ mScreenshot.setMaxWidth(screenshot.getWidth() / 3);
+ mScreenshot.setMaxHeight(screenshot.getHeight() / 3);
+ mFullScreenshot.setImageBitmap(screenshot);
+ } else {
+ mScreenshot.setImageDrawable(null);
+ mFullScreenshot.setImageDrawable(null);
+ }
}
}
void updateState() {
+ if (mTopContent == null) {
+ return;
+ }
if (mState == STATE_IDLE) {
mTopContent.setVisibility(View.VISIBLE);
mBottomContent.setVisibility(View.GONE);
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 63498f7..ff306ce 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -2204,8 +2204,10 @@
package.string(), package.size(),
&specFlags);
if (rid != 0) {
- if (onlyPublic) {
- if ((specFlags & ResTable_typeSpec::SPEC_PUBLIC) == 0) {
+ if (onlyPublic && (specFlags & ResTable_typeSpec::SPEC_PUBLIC) == 0) {
+ // If this is a feature split and the resource has the same
+ // package name as us, then everything is public.
+ if (mPackageType != AppFeature || mAssetsPackage != package) {
return 0;
}
}
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index 1123967..150dc58 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -19,6 +19,7 @@
#include <sstream>
#include "androidfw/ResourceTypes.h"
+#include "androidfw/ResourceUtils.h"
#include "NameMangler.h"
#include "SdkConstants.h"
@@ -69,31 +70,6 @@
return name_out;
}
-bool ExtractResourceName(const StringPiece& str, StringPiece* out_package,
- StringPiece* out_type, StringPiece* out_entry) {
- bool has_package_separator = false;
- bool has_type_separator = false;
- const char* start = str.data();
- const char* end = start + str.size();
- const char* current = start;
- while (current != end) {
- if (out_type->size() == 0 && *current == '/') {
- has_type_separator = true;
- out_type->assign(start, current - start);
- start = current + 1;
- } else if (out_package->size() == 0 && *current == ':') {
- has_package_separator = true;
- out_package->assign(start, current - start);
- start = current + 1;
- }
- current++;
- }
- out_entry->assign(start, end - start);
-
- return !(has_package_separator && out_package->empty()) &&
- !(has_type_separator && out_type->empty());
-}
-
bool ParseResourceName(const StringPiece& str, ResourceNameRef* out_ref,
bool* out_private) {
if (str.empty()) {
@@ -110,8 +86,8 @@
StringPiece package;
StringPiece type;
StringPiece entry;
- if (!ExtractResourceName(str.substr(offset, str.size() - offset), &package,
- &type, &entry)) {
+ if (!android::ExtractResourceName(str.substr(offset, str.size() - offset), &package, &type,
+ &entry)) {
return false;
}
@@ -197,8 +173,8 @@
StringPiece package;
StringPiece type;
StringPiece entry;
- if (!ExtractResourceName(trimmed_str.substr(1, trimmed_str.size() - 1),
- &package, &type, &entry)) {
+ if (!android::ExtractResourceName(trimmed_str.substr(1, trimmed_str.size() - 1), &package,
+ &type, &entry)) {
return false;
}
@@ -258,7 +234,7 @@
ref.type = ResourceType::kStyle;
StringPiece type_str;
- ExtractResourceName(name, &ref.package, &type_str, &ref.entry);
+ android::ExtractResourceName(name, &ref.package, &type_str, &ref.entry);
if (!type_str.empty()) {
// If we have a type, make sure it is a Style.
const ResourceType* parsed_type = ParseResourceType(type_str);
diff --git a/tools/aapt2/ResourceUtils.h b/tools/aapt2/ResourceUtils.h
index bd3a8e3..59b78f4 100644
--- a/tools/aapt2/ResourceUtils.h
+++ b/tools/aapt2/ResourceUtils.h
@@ -29,18 +29,6 @@
namespace aapt {
namespace ResourceUtils {
-/*
- * Extracts the package, type, and name from a string of the format:
- *
- * [package:]type/name
- *
- * where the package can be empty. Validation must be performed on each
- * individual extracted piece to verify that the pieces are valid.
- * Returns false if there was no package but a ':' was present.
- */
-bool ExtractResourceName(const android::StringPiece& str, android::StringPiece* out_package,
- android::StringPiece* out_type, android::StringPiece* out_entry);
-
/**
* Returns true if the string was parsed as a resource name
* ([*][package:]type/name), with
diff --git a/tools/layoutlib/.idea/libraries/mockito.xml b/tools/layoutlib/.idea/libraries/mockito.xml
new file mode 100644
index 0000000..032963e
--- /dev/null
+++ b/tools/layoutlib/.idea/libraries/mockito.xml
@@ -0,0 +1,9 @@
+<component name="libraryTable">
+ <library name="mockito">
+ <CLASSES>
+ <root url="jar://$PROJECT_DIR$/../../../../out/host/common/obj/JAVA_LIBRARIES/mockito-host_intermediates/javalib.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+</component>
\ No newline at end of file
diff --git a/tools/layoutlib/.idea/libraries/objenesis.xml b/tools/layoutlib/.idea/libraries/objenesis.xml
new file mode 100644
index 0000000..1484de5
--- /dev/null
+++ b/tools/layoutlib/.idea/libraries/objenesis.xml
@@ -0,0 +1,9 @@
+<component name="libraryTable">
+ <library name="objenesis">
+ <CLASSES>
+ <root url="jar://$PROJECT_DIR$/../../../../out/host/common/obj/JAVA_LIBRARIES/objenesis-host_intermediates/javalib.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+</component>
\ No newline at end of file
diff --git a/tools/layoutlib/bridge/bridge.iml b/tools/layoutlib/bridge/bridge.iml
index fbaed52..85ec3eb 100644
--- a/tools/layoutlib/bridge/bridge.iml
+++ b/tools/layoutlib/bridge/bridge.iml
@@ -86,5 +86,7 @@
</library>
</orderEntry>
<orderEntry type="library" scope="TEST" name="junit" level="project" />
+ <orderEntry type="library" scope="TEST" name="mockito" level="project" />
+ <orderEntry type="library" scope="TEST" name="objenesis" level="project" />
</component>
</module>
\ No newline at end of file
diff --git a/tools/layoutlib/bridge/src/android/util/BridgeXmlPullAttributes.java b/tools/layoutlib/bridge/src/android/util/BridgeXmlPullAttributes.java
index 138b2d5..9fd1e15 100644
--- a/tools/layoutlib/bridge/src/android/util/BridgeXmlPullAttributes.java
+++ b/tools/layoutlib/bridge/src/android/util/BridgeXmlPullAttributes.java
@@ -16,6 +16,7 @@
package android.util;
+import com.android.ide.common.rendering.api.AttrResourceValue;
import com.android.ide.common.rendering.api.RenderResources;
import com.android.ide.common.rendering.api.ResourceValue;
import com.android.internal.util.XmlUtils;
@@ -27,6 +28,11 @@
import org.xmlpull.v1.XmlPullParser;
+import android.annotation.NonNull;
+
+import java.util.Map;
+import java.util.function.Function;
+
/**
* A correct implementation of the {@link AttributeSet} interface on top of a XmlPullParser
*/
@@ -34,12 +40,30 @@
private final BridgeContext mContext;
private final boolean mPlatformFile;
+ private final Function<String, Map<String, Integer>> mFrameworkEnumValueSupplier;
+ private final Function<String, Map<String, Integer>> mProjectEnumValueSupplier;
- public BridgeXmlPullAttributes(XmlPullParser parser, BridgeContext context,
- boolean platformFile) {
+ // VisibleForTesting
+ BridgeXmlPullAttributes(@NonNull XmlPullParser parser, @NonNull BridgeContext context,
+ boolean platformFile,
+ @NonNull Function<String, Map<String, Integer>> frameworkEnumValueSupplier,
+ @NonNull Function<String, Map<String, Integer>> projectEnumValueSupplier) {
super(parser);
mContext = context;
mPlatformFile = platformFile;
+ mFrameworkEnumValueSupplier = frameworkEnumValueSupplier;
+ mProjectEnumValueSupplier = projectEnumValueSupplier;
+ }
+
+ public BridgeXmlPullAttributes(@NonNull XmlPullParser parser, @NonNull BridgeContext context,
+ boolean platformFile) {
+ this(parser, context, platformFile, Bridge::getEnumValues, attrName -> {
+ // get the styleable matching the resolved name
+ RenderResources res = context.getRenderResources();
+ ResourceValue attr = res.getProjectResource(ResourceType.ATTR, attrName);
+ return attr instanceof AttrResourceValue ?
+ ((AttrResourceValue) attr).getAttributeValues() : null;
+ });
}
/*
@@ -59,12 +83,8 @@
String ns = mParser.getAttributeNamespace(index);
if (BridgeConstants.NS_RESOURCES.equals(ns)) {
- Integer v = Bridge.getResourceId(ResourceType.ATTR, name);
- if (v != null) {
- return v.intValue();
- }
+ return Bridge.getResourceId(ResourceType.ATTR, name);
- return 0;
}
// this is not an attribute in the android namespace, we query the customviewloader, if
@@ -72,7 +92,7 @@
if (mContext.getLayoutlibCallback().getNamespace().equals(ns)) {
Integer v = mContext.getLayoutlibCallback().getResourceId(ResourceType.ATTR, name);
if (v != null) {
- return v.intValue();
+ return v;
}
}
@@ -121,20 +141,38 @@
}
@Override
- public int getAttributeIntValue(String namespace, String attribute,
- int defaultValue) {
+ public int getAttributeIntValue(String namespace, String attribute, int defaultValue) {
String value = getAttributeValue(namespace, attribute);
- if (value != null) {
- ResourceValue r = getResourceValue(value);
-
- if (r != null) {
- value = r.getValue();
- }
-
- return XmlUtils.convertValueToInt(value, defaultValue);
+ if (value == null) {
+ return defaultValue;
}
- return defaultValue;
+ ResourceValue r = getResourceValue(value);
+
+ if (r != null) {
+ value = r.getValue();
+ }
+
+ if (value.charAt(0) == '#') {
+ return ResourceHelper.getColor(value);
+ }
+
+ try {
+ return XmlUtils.convertValueToInt(value, defaultValue);
+ } catch (NumberFormatException e) {
+ // This is probably an enum
+ Map<String, Integer> enumValues = BridgeConstants.NS_RESOURCES.equals(namespace) ?
+ mFrameworkEnumValueSupplier.apply(attribute) :
+ mProjectEnumValueSupplier.apply(attribute);
+
+ Integer enumValue = enumValues != null ? enumValues.get(value) : null;
+ if (enumValue != null) {
+ return enumValue;
+ }
+
+ // We weren't able to find the enum int value
+ throw e;
+ }
}
@Override
@@ -203,21 +241,9 @@
@Override
public int getAttributeIntValue(int index, int defaultValue) {
- String value = getAttributeValue(index);
- if (value != null) {
- ResourceValue r = getResourceValue(value);
-
- if (r != null) {
- value = r.getValue();
- }
-
- if (value.charAt(0) == '#') {
- return ResourceHelper.getColor(value);
- }
- return XmlUtils.convertValueToInt(value, defaultValue);
- }
-
- return defaultValue;
+ return getAttributeIntValue(mParser.getAttributeNamespace(index),
+ getAttributeName(index)
+ , defaultValue);
}
@Override
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index dff4f69..c9b04dc 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -111,7 +111,7 @@
* Custom implementation of Context/Activity to handle non compiled resources.
*/
@SuppressWarnings("deprecation") // For use of Pair.
-public final class BridgeContext extends Context {
+public class BridgeContext extends Context {
private static final String PREFIX_THEME_APPCOMPAT = "Theme.AppCompat";
private static final Map<String, ResourceValue> FRAMEWORK_PATCHED_VALUES = new HashMap<>(2);
diff --git a/tools/layoutlib/bridge/tests/Android.mk b/tools/layoutlib/bridge/tests/Android.mk
index 33d55de..1b65eee 100644
--- a/tools/layoutlib/bridge/tests/Android.mk
+++ b/tools/layoutlib/bridge/tests/Android.mk
@@ -31,7 +31,8 @@
tools-common-prebuilt \
sdk-common \
junit-host \
- guavalib
+ guavalib \
+ mockito-host
include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/activity.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/activity.png
index 199ea60..affc31e 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/activity.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/activity.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
index 89ff5db..a53dcba 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png
index 1f4405d..88fa9dd 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/animated_vector.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/animated_vector.png
index 26aed6a..e33f92d 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/animated_vector.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/animated_vector.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/animated_vector_1.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/animated_vector_1.png
index aaf1514..915868c 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/animated_vector_1.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/animated_vector_1.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/array_check.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/array_check.png
index c3bd708..ee72a6f 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/array_check.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/array_check.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/expand_horz_layout.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/expand_horz_layout.png
index 0c16215..781d617 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/expand_horz_layout.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/expand_horz_layout.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/expand_vert_layout.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/expand_vert_layout.png
index 81755ce..5b64d33 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/expand_vert_layout.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/expand_vert_layout.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners.png
index 868cd51..a8567b3 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent.png
index 601f711f..5ae95ea3 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent_land.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent_land.png
index 0b8f1a9..b2b6a97 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent_land.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent_land.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/scrolled.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/scrolled.png
index 87bd502..cf1a769 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/scrolled.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/scrolled.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity-old-theme.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity-old-theme.png
index eb431b0..e0abcf4 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity-old-theme.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity-old-theme.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity.png
index 4e448c8..3d0fbd6 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity_noactionbar.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity_noactionbar.png
index b756719..86b00415 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity_noactionbar.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity_noactionbar.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable.png
index 466eca8..7bbae09 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_91383.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_91383.png
index 940fe5b..e9dca692 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_91383.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_91383.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/src/android/util/BridgeXmlPullAttributesTest.java b/tools/layoutlib/bridge/tests/src/android/util/BridgeXmlPullAttributesTest.java
new file mode 100644
index 0000000..2fcec8e
--- /dev/null
+++ b/tools/layoutlib/bridge/tests/src/android/util/BridgeXmlPullAttributesTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.util;
+
+import com.android.ide.common.rendering.api.RenderResources;
+import com.android.layoutlib.bridge.BridgeConstants;
+import com.android.layoutlib.bridge.android.BridgeContext;
+
+import org.junit.Test;
+import org.xmlpull.v1.XmlPullParser;
+
+import com.google.common.collect.ImmutableMap;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class BridgeXmlPullAttributesTest {
+ @Test
+ public void testGetAttributeIntValueForEnums() {
+ RenderResources renderResources = new RenderResources();
+
+ XmlPullParser parser = mock(XmlPullParser.class);
+ when(parser.getAttributeValue(BridgeConstants.NS_RESOURCES, "layout_width"))
+ .thenReturn("match_parent");
+ when(parser.getAttributeName(0)).thenReturn("layout_width");
+ when(parser.getAttributeNamespace(0)).thenReturn(BridgeConstants.NS_RESOURCES);
+ // Return every value twice since there is one test using name and other using index
+ when(parser.getAttributeValue("http://custom", "my_custom_attr"))
+ .thenReturn("a", "a", "b", "b", "invalid", "invalid");
+ when(parser.getAttributeName(1)).thenReturn("my_custom_attr");
+ when(parser.getAttributeNamespace(1)).thenReturn("http://custom");
+
+ BridgeContext context = mock(BridgeContext.class);
+ when(context.getRenderResources()).thenReturn(renderResources);
+
+ BridgeXmlPullAttributes attributes = new BridgeXmlPullAttributes(
+ parser,
+ context,
+ false,
+ attrName -> {
+ if ("layout_width".equals(attrName)) {
+ return ImmutableMap.of(
+ "match_parent", 123);
+ }
+ return ImmutableMap.of();
+ },
+ attrName -> {
+ if ("my_custom_attr".equals(attrName)) {
+ return ImmutableMap.of(
+ "a", 1,
+ "b", 2
+ );
+ }
+ return ImmutableMap.of();
+ });
+
+ // Test a framework defined enum attribute
+ assertEquals(123, attributes.getAttributeIntValue(BridgeConstants.NS_RESOURCES,
+ "layout_width", 500));
+ assertEquals(123, attributes.getAttributeIntValue(0, 500));
+ // Test non existing attribute (it should return the default value)
+ assertEquals(500, attributes.getAttributeIntValue(BridgeConstants.NS_RESOURCES,
+ "layout_height", 500));
+ assertEquals(500, attributes.getAttributeIntValue(2, 500));
+
+ // Test project defined enum attribute
+ assertEquals(1, attributes.getAttributeIntValue("http://custom",
+ "my_custom_attr", 500));
+ assertEquals(1, attributes.getAttributeIntValue(1, 500));
+ assertEquals(2, attributes.getAttributeIntValue("http://custom",
+ "my_custom_attr", 500));
+ assertEquals(2, attributes.getAttributeIntValue(1, 500));
+ // Test an invalid enum
+ boolean exception = false;
+ try {
+ attributes.getAttributeIntValue("http://custom", "my_custom_attr", 500);
+ } catch(NumberFormatException e) {
+ exception = true;
+ }
+ assertTrue(exception);
+ exception = false;
+ try {
+ attributes.getAttributeIntValue(1, 500);
+ } catch(NumberFormatException e) {
+ exception = true;
+ }
+ assertTrue(exception);
+
+ // Test non existing project attribute
+ assertEquals(500, attributes.getAttributeIntValue("http://custom",
+ "my_other_attr", 500));
+ }
+
+}
\ No newline at end of file
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/ImageUtils.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/ImageUtils.java
index 18c6629..cdf5633 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/ImageUtils.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/ImageUtils.java
@@ -54,7 +54,7 @@
*/
private static final boolean FAIL_ON_MISSING_THUMBNAIL = true;
- private static final int THUMBNAIL_SIZE = 250;
+ private static final int THUMBNAIL_SIZE = 1000;
private static final double MAX_PERCENT_DIFFERENCE = 0.3;
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index dbf8cc1..97a15e4 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -305,7 +305,9 @@
/**
* Priority determines the preference given to a network by {@code wpa_supplicant}
* when choosing an access point with which to associate.
+ * @deprecated Priority is no longer used.
*/
+ @Deprecated
public int priority;
/**
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 0bfb955..f790332 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -263,11 +263,17 @@
public static final int MSCHAPV2 = 3;
/** Generic Token Card */
public static final int GTC = 4;
+ /** EAP-Subscriber Identity Module */
+ public static final int SIM = 5;
+ /** EAP-Authentication and Key Agreement */
+ public static final int AKA = 6;
+ /** EAP-Authentication and Key Agreement Prime */
+ public static final int AKA_PRIME = 7;
private static final String AUTH_PREFIX = "auth=";
private static final String AUTHEAP_PREFIX = "autheap=";
/** @hide */
public static final String[] strings = {EMPTY_VALUE, "PAP", "MSCHAP",
- "MSCHAPV2", "GTC" };
+ "MSCHAPV2", "GTC", "SIM", "AKA", "AKA'" };
/** Prevent initialization */
private Phase2() {}
@@ -426,6 +432,9 @@
case Phase2.MSCHAP:
case Phase2.MSCHAPV2:
case Phase2.GTC:
+ case Phase2.SIM:
+ case Phase2.AKA:
+ case Phase2.AKA_PRIME:
mPhase2Method = phase2Method;
break;
default:
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 3fb8ef3..ed6a166 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -838,7 +838,8 @@
}
/**
- * Return a list of all the networks configured in the supplicant.
+ * Return a list of all the networks configured for the current foreground
+ * user.
* Not all fields of WifiConfiguration are returned. Only the following
* fields are filled in:
* <ul>
@@ -1057,8 +1058,12 @@
* Remove the specified network from the list of configured networks.
* This may result in the asynchronous delivery of state change
* events.
- * @param netId the integer that identifies the network configuration
- * to the supplicant
+ *
+ * Applications are not allowed to remove networks created by other
+ * applications.
+ *
+ * @param netId the ID of the network as returned by {@link #addNetwork} or {@link
+ * #getConfiguredNetworks}.
* @return {@code true} if the operation succeeded
*/
public boolean removeNetwork(int netId) {
@@ -1071,8 +1076,7 @@
/**
* Allow a previously configured network to be associated with. If
- * <code>disableOthers</code> is true, then all other configured
- * networks are disabled, and an attempt to connect to the selected
+ * <code>attemptConnect</code> is true, an attempt to connect to the selected
* network is initiated. This may result in the asynchronous delivery
* of state change events.
* <p>
@@ -1089,14 +1093,17 @@
* {@link Network#openConnection(java.net.URL)}, or
* {@link ConnectivityManager#bindProcessToNetwork} to do so.
*
- * @param netId the ID of the network in the list of configured networks
- * @param disableOthers if true, disable all other networks. The way to
- * select a particular network to connect to is specify {@code true}
- * for this parameter.
+ * Applications are not allowed to enable networks created by other
+ * applications.
+ *
+ * @param netId the ID of the network as returned by {@link #addNetwork} or {@link
+ * #getConfiguredNetworks}.
+ * @param attemptConnect The way to select a particular network to connect to is specify
+ * {@code true} for this parameter.
* @return {@code true} if the operation succeeded
*/
- public boolean enableNetwork(int netId, boolean disableOthers) {
- final boolean pin = disableOthers && mTargetSdkVersion < Build.VERSION_CODES.LOLLIPOP;
+ public boolean enableNetwork(int netId, boolean attemptConnect) {
+ final boolean pin = attemptConnect && mTargetSdkVersion < Build.VERSION_CODES.LOLLIPOP;
if (pin) {
NetworkRequest request = new NetworkRequest.Builder()
.clearCapabilities()
@@ -1107,7 +1114,7 @@
boolean success;
try {
- success = mService.enableNetwork(netId, disableOthers);
+ success = mService.enableNetwork(netId, attemptConnect);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1123,7 +1130,12 @@
* Disable a configured network. The specified network will not be
* a candidate for associating. This may result in the asynchronous
* delivery of state change events.
- * @param netId the ID of the network as returned by {@link #addNetwork}.
+ *
+ * Applications are not allowed to disable networks created by other
+ * applications.
+ *
+ * @param netId the ID of the network as returned by {@link #addNetwork} or {@link
+ * #getConfiguredNetworks}.
* @return {@code true} if the operation succeeded
*/
public boolean disableNetwork(int netId) {
@@ -1182,15 +1194,11 @@
* Check that the supplicant daemon is responding to requests.
* @return {@code true} if we were able to communicate with the supplicant and
* it returned the expected response to the PING message.
+ * @deprecated Will return the output of {@link #isWifiEnabled()} instead.
*/
+ @Deprecated
public boolean pingSupplicant() {
- if (mService == null)
- return false;
- try {
- return mService.pingSupplicant();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return isWifiEnabled();
}
/** @hide */
@@ -1509,14 +1517,18 @@
}
/**
- * Tell the supplicant to persist the current list of configured networks.
+ * Tell the device to persist the current list of configured networks.
* <p>
* Note: It is possible for this method to change the network IDs of
* existing networks. You should assume the network IDs can be different
* after calling this method.
*
* @return {@code true} if the operation succeeded
+ * @deprecated There is no need to call this method -
+ * {@link #addNetwork(WifiConfiguration)}, {@link #updateNetwork(WifiConfiguration)}
+ * and {@link #removeNetwork(int)} already persist the configurations automatically.
*/
+ @Deprecated
public boolean saveConfiguration() {
try {
return mService.saveConfiguration();
@@ -2095,7 +2107,7 @@
/**
* Connect to a network with the given configuration. The network also
- * gets added to the supplicant configuration.
+ * gets added to the list of configured networks for the foreground user.
*
* For a new network, this function is used instead of a
* sequence of addNetwork(), enableNetwork(), saveConfiguration() and
@@ -2124,8 +2136,8 @@
* This function is used instead of a enableNetwork(), saveConfiguration() and
* reconnect()
*
- * @param networkId the network id identifiying the network in the
- * supplicant configuration list
+ * @param networkId the ID of the network as returned by {@link #addNetwork} or {@link
+ * getConfiguredNetworks}.
* @param listener for callbacks on success or failure. Can be null.
* @throws IllegalStateException if the WifiManager instance needs to be
* initialized again
@@ -2137,9 +2149,9 @@
}
/**
- * Save the given network in the supplicant config. If the network already
- * exists, the configuration is updated. A new network is enabled
- * by default.
+ * Save the given network to the list of configured networks for the
+ * foreground user. If the network already exists, the configuration
+ * is updated. Any new network is enabled by default.
*
* For a new network, this function is used instead of a
* sequence of addNetwork(), enableNetwork() and saveConfiguration().
@@ -2160,7 +2172,8 @@
}
/**
- * Delete the network in the supplicant config.
+ * Delete the network from the list of configured networks for the
+ * foreground user.
*
* This function is used instead of a sequence of removeNetwork()
* and saveConfiguration().
@@ -2851,7 +2864,8 @@
/**
* Restore state from the older version of back up data.
- * The old backup data was essentially a backup of wpa_supplicant.conf & ipconfig.txt file.
+ * The old backup data was essentially a backup of wpa_supplicant.conf
+ * and ipconfig.txt file.
* @hide
*/
public void restoreSupplicantBackupData(byte[] supplicantData, byte[] ipConfigData) {
diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index 7b73b4b..1f661c4 100644
--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -120,7 +120,7 @@
public void setUpdateIdentifier(int updateIdentifier) {
mUpdateIdentifier = updateIdentifier;
}
- public int getUpdateIdentififer() {
+ public int getUpdateIdentifier() {
return mUpdateIdentifier;
}
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
index 025d4d3..620759d 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
@@ -100,7 +100,7 @@
public void setCheckAaaServerCertStatus(boolean checkAaaServerCertStatus) {
mCheckAaaServerCertStatus = checkAaaServerCertStatus;
}
- public boolean getCheckAaaServerStatus() {
+ public boolean getCheckAaaServerCertStatus() {
return mCheckAaaServerCertStatus;
}
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java b/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java
index 7a46129..8ec40c0 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java
@@ -131,7 +131,7 @@
public void setMatchAnyOis(long[] matchAnyOis) {
mMatchAnyOis = matchAnyOis;
}
- public long[] getMatchAnysOis() {
+ public long[] getMatchAnyOis() {
return mMatchAnyOis;
}
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Policy.java b/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
index caca0e4..63238e8 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
@@ -77,7 +77,7 @@
public void setMinHomeDownlinkBandwidth(long minHomeDownlinkBandwidth) {
mMinHomeDownlinkBandwidth = minHomeDownlinkBandwidth;
}
- public long getMinHomeDownlinkBandWidht() {
+ public long getMinHomeDownlinkBandwidth() {
return mMinHomeDownlinkBandwidth;
}
private long mMinHomeUplinkBandwidth = Long.MIN_VALUE;
diff --git a/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java b/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
index fa546a5..c4d2d32 100644
--- a/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
@@ -283,6 +283,21 @@
assertEquals("\"auth=GTC\"", getSupplicantPhase2Method());
}
+ /** Verfies PEAP/SIM, PEAP/AKA, PEAP/AKA'. */
+ @Test
+ public void peapSimAkaAkaPrime() {
+ mEnterpriseConfig.setEapMethod(Eap.PEAP);
+ mEnterpriseConfig.setPhase2Method(Phase2.SIM);
+ assertEquals("PEAP", getSupplicantEapMethod());
+ assertEquals("\"auth=SIM\"", getSupplicantPhase2Method());
+
+ mEnterpriseConfig.setPhase2Method(Phase2.AKA);
+ assertEquals("\"auth=AKA\"", getSupplicantPhase2Method());
+
+ mEnterpriseConfig.setPhase2Method(Phase2.AKA_PRIME);
+ assertEquals("\"auth=AKA'\"", getSupplicantPhase2Method());
+ }
+
/** Verfies that the copy constructor preseves the inner method information. */
@Test
public void copyConstructor() {