diff options
236 files changed, 5393 insertions, 1417 deletions
diff --git a/api/current.txt b/api/current.txt index eaa35711d30f..82dd59069c87 100644 --- a/api/current.txt +++ b/api/current.txt @@ -7182,9 +7182,10 @@ package android.app.slice { method public java.util.List<android.app.slice.SliceSpec> getPinnedSpecs(android.net.Uri); method public java.util.Collection<android.net.Uri> getSliceDescendants(android.net.Uri); method public void pinSlice(android.net.Uri, java.util.List<android.app.slice.SliceSpec>); - method public void registerSliceCallback(android.net.Uri, android.app.slice.SliceManager.SliceCallback, java.util.List<android.app.slice.SliceSpec>); - method public void registerSliceCallback(android.net.Uri, android.app.slice.SliceManager.SliceCallback, java.util.List<android.app.slice.SliceSpec>, android.os.Handler); - method public void registerSliceCallback(android.net.Uri, android.app.slice.SliceManager.SliceCallback, java.util.List<android.app.slice.SliceSpec>, java.util.concurrent.Executor); + method public deprecated void registerSliceCallback(android.net.Uri, android.app.slice.SliceManager.SliceCallback, java.util.List<android.app.slice.SliceSpec>); + method public deprecated void registerSliceCallback(android.net.Uri, android.app.slice.SliceManager.SliceCallback, java.util.List<android.app.slice.SliceSpec>, java.util.concurrent.Executor); + method public void registerSliceCallback(android.net.Uri, java.util.List<android.app.slice.SliceSpec>, android.app.slice.SliceManager.SliceCallback); + method public void registerSliceCallback(android.net.Uri, java.util.List<android.app.slice.SliceSpec>, java.util.concurrent.Executor, android.app.slice.SliceManager.SliceCallback); method public void unpinSlice(android.net.Uri); method public void unregisterSliceCallback(android.net.Uri, android.app.slice.SliceManager.SliceCallback); } @@ -13505,6 +13506,58 @@ package android.graphics { ctor public EmbossMaskFilter(float[], float, float, float); } + public final class ImageDecoder implements java.lang.AutoCloseable { + method public void close(); + method public static android.graphics.ImageDecoder.Source createSource(android.content.ContentResolver, android.net.Uri); + method public static android.graphics.ImageDecoder.Source createSource(java.nio.ByteBuffer); + method public static android.graphics.ImageDecoder.Source createSource(java.io.File); + method public static android.graphics.Bitmap decodeBitmap(android.graphics.ImageDecoder.Source, android.graphics.ImageDecoder.OnHeaderDecodedListener) throws java.io.IOException; + method public static android.graphics.Bitmap decodeBitmap(android.graphics.ImageDecoder.Source) throws java.io.IOException; + method public static android.graphics.drawable.Drawable decodeDrawable(android.graphics.ImageDecoder.Source, android.graphics.ImageDecoder.OnHeaderDecodedListener) throws java.io.IOException; + method public static android.graphics.drawable.Drawable decodeDrawable(android.graphics.ImageDecoder.Source) throws java.io.IOException; + method public android.util.Size getSampledSize(int); + method public void setAllocator(int); + method public void setAsAlphaMask(boolean); + method public void setCrop(android.graphics.Rect); + method public void setMutable(boolean); + method public void setOnPartialImageListener(android.graphics.ImageDecoder.OnPartialImageListener); + method public void setPostProcessor(android.graphics.PostProcessor); + method public void setPreferRamOverQuality(boolean); + method public void setRequireUnpremultiplied(boolean); + method public void setResize(int, int); + method public void setResize(int); + field public static final int ALLOCATOR_DEFAULT = 0; // 0x0 + field public static final int ALLOCATOR_HARDWARE = 3; // 0x3 + field public static final int ALLOCATOR_SHARED_MEMORY = 2; // 0x2 + field public static final int ALLOCATOR_SOFTWARE = 1; // 0x1 + field public static final int ERROR_SOURCE_ERROR = 3; // 0x3 + field public static final int ERROR_SOURCE_EXCEPTION = 1; // 0x1 + field public static final int ERROR_SOURCE_INCOMPLETE = 2; // 0x2 + } + + public static abstract class ImageDecoder.Error implements java.lang.annotation.Annotation { + } + + public static class ImageDecoder.ImageInfo { + method public java.lang.String getMimeType(); + method public android.util.Size getSize(); + } + + public static class ImageDecoder.IncompleteException extends java.io.IOException { + ctor public ImageDecoder.IncompleteException(); + } + + public static abstract interface ImageDecoder.OnHeaderDecodedListener { + method public abstract void onHeaderDecoded(android.graphics.ImageDecoder, android.graphics.ImageDecoder.ImageInfo, android.graphics.ImageDecoder.Source); + } + + public static abstract interface ImageDecoder.OnPartialImageListener { + method public abstract boolean onPartialImage(int, android.graphics.ImageDecoder.Source); + } + + public static abstract class ImageDecoder.Source { + } + public class ImageFormat { ctor public ImageFormat(); method public static int getBitsPerPixel(int); @@ -14075,6 +14128,10 @@ package android.graphics { ctor public PorterDuffXfermode(android.graphics.PorterDuff.Mode); } + public abstract interface PostProcessor { + method public abstract int onPostProcess(android.graphics.Canvas); + } + public class RadialGradient extends android.graphics.Shader { ctor public RadialGradient(float, float, float, int[], float[], android.graphics.Shader.TileMode); ctor public RadialGradient(float, float, float, int, int, android.graphics.Shader.TileMode); @@ -21717,6 +21774,7 @@ package android.media { method public android.media.AudioFocusRequest.Builder setAcceptsDelayedFocusGain(boolean); method public android.media.AudioFocusRequest.Builder setAudioAttributes(android.media.AudioAttributes); method public android.media.AudioFocusRequest.Builder setFocusGain(int); + method public android.media.AudioFocusRequest.Builder setForceDucking(boolean); method public android.media.AudioFocusRequest.Builder setOnAudioFocusChangeListener(android.media.AudioManager.OnAudioFocusChangeListener); method public android.media.AudioFocusRequest.Builder setOnAudioFocusChangeListener(android.media.AudioManager.OnAudioFocusChangeListener, android.os.Handler); method public android.media.AudioFocusRequest.Builder setWillPauseWhenDucked(boolean); @@ -23079,24 +23137,29 @@ package android.media { method public android.media.MediaDescription.Builder setTitle(java.lang.CharSequence); } - public final class MediaDrm { + public final class MediaDrm implements java.lang.AutoCloseable { ctor public MediaDrm(java.util.UUID) throws android.media.UnsupportedSchemeException; + method public void close(); method public void closeSession(byte[]); - method protected void finalize(); + method public int getConnectedHdcpLevel(); method public android.media.MediaDrm.CryptoSession getCryptoSession(byte[], java.lang.String, java.lang.String); method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], byte[], java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>) throws android.media.NotProvisionedException; + method public int getMaxHdcpLevel(); + method public int getMaxSessionCount(); + method public int getOpenSessionCount(); method public byte[] getPropertyByteArray(java.lang.String); method public java.lang.String getPropertyString(java.lang.String); method public android.media.MediaDrm.ProvisionRequest getProvisionRequest(); method public byte[] getSecureStop(byte[]); method public java.util.List<byte[]> getSecureStops(); + method public int getSecurityLevel(byte[]); method public static final boolean isCryptoSchemeSupported(java.util.UUID); method public static final boolean isCryptoSchemeSupported(java.util.UUID, java.lang.String); method public byte[] openSession() throws android.media.NotProvisionedException, android.media.ResourceBusyException; method public byte[] provideKeyResponse(byte[], byte[]) throws android.media.DeniedByServerException, android.media.NotProvisionedException; method public void provideProvisionResponse(byte[]) throws android.media.DeniedByServerException; method public java.util.HashMap<java.lang.String, java.lang.String> queryKeyStatus(byte[]); - method public final void release(); + method public deprecated void release(); method public void releaseAllSecureStops(); method public void releaseSecureStops(byte[]); method public void removeKeys(byte[]); @@ -23106,11 +23169,22 @@ package android.media { method public void setOnKeyStatusChangeListener(android.media.MediaDrm.OnKeyStatusChangeListener, android.os.Handler); method public void setPropertyByteArray(java.lang.String, byte[]); method public void setPropertyString(java.lang.String, java.lang.String); + method public void setSecurityLevel(byte[], int); field public static final deprecated int EVENT_KEY_EXPIRED = 3; // 0x3 field public static final int EVENT_KEY_REQUIRED = 2; // 0x2 field public static final deprecated int EVENT_PROVISION_REQUIRED = 1; // 0x1 field public static final int EVENT_SESSION_RECLAIMED = 5; // 0x5 field public static final int EVENT_VENDOR_DEFINED = 4; // 0x4 + field public static final int HDCP_LEVEL_UNKNOWN = 0; // 0x0 + field public static final int HDCP_NONE = 1; // 0x1 + field public static final int HDCP_NO_DIGITAL_OUTPUT = 2147483647; // 0x7fffffff + field public static final int HDCP_V1 = 2; // 0x2 + field public static final int HDCP_V2 = 3; // 0x3 + field public static final int HDCP_V2_1 = 4; // 0x4 + field public static final int HDCP_V2_2 = 5; // 0x5 + field public static final int HW_SECURE_ALL = 5; // 0x5 + field public static final int HW_SECURE_CRYPTO = 3; // 0x3 + field public static final int HW_SECURE_DECODE = 4; // 0x4 field public static final int KEY_TYPE_OFFLINE = 2; // 0x2 field public static final int KEY_TYPE_RELEASE = 3; // 0x3 field public static final int KEY_TYPE_STREAMING = 1; // 0x1 @@ -23119,6 +23193,9 @@ package android.media { field public static final java.lang.String PROPERTY_DEVICE_UNIQUE_ID = "deviceUniqueId"; field public static final java.lang.String PROPERTY_VENDOR = "vendor"; field public static final java.lang.String PROPERTY_VERSION = "version"; + field public static final int SECURITY_LEVEL_UNKNOWN = 0; // 0x0 + field public static final int SW_SECURE_CRYPTO = 1; // 0x1 + field public static final int SW_SECURE_DECODE = 2; // 0x2 } public final class MediaDrm.CryptoSession { @@ -23128,6 +23205,9 @@ package android.media { method public boolean verify(byte[], byte[], byte[]); } + public static abstract class MediaDrm.HdcpLevel implements java.lang.annotation.Annotation { + } + public static final class MediaDrm.KeyRequest { method public byte[] getData(); method public java.lang.String getDefaultUrl(); @@ -23168,6 +23248,9 @@ package android.media { method public java.lang.String getDefaultUrl(); } + public static abstract class MediaDrm.SecurityLevel implements java.lang.annotation.Annotation { + } + public class MediaDrmException extends java.lang.Exception { ctor public MediaDrmException(java.lang.String); } @@ -26167,6 +26250,7 @@ package android.net { method public deprecated android.net.NetworkInfo getNetworkInfo(int); method public android.net.NetworkInfo getNetworkInfo(android.net.Network); method public deprecated int getNetworkPreference(); + method public byte[] getNetworkWatchlistConfigHash(); method public static deprecated android.net.Network getProcessDefaultNetwork(); method public int getRestrictBackgroundStatus(); method public boolean isActiveNetworkMetered(); diff --git a/api/system-current.txt b/api/system-current.txt index 6119d5f0c548..97f82e99fe6e 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -794,8 +794,6 @@ package android.content { field public static final java.lang.String ACTION_QUERY_PACKAGE_RESTART = "android.intent.action.QUERY_PACKAGE_RESTART"; field public static final java.lang.String ACTION_RESOLVE_INSTANT_APP_PACKAGE = "android.intent.action.RESOLVE_INSTANT_APP_PACKAGE"; field public static final java.lang.String ACTION_REVIEW_PERMISSIONS = "android.intent.action.REVIEW_PERMISSIONS"; - field public static final java.lang.String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.intent.action.SIM_APPLICATION_STATE_CHANGED"; - field public static final java.lang.String ACTION_SIM_CARD_STATE_CHANGED = "android.intent.action.SIM_CARD_STATE_CHANGED"; field public static final deprecated java.lang.String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED"; field public static final java.lang.String ACTION_UPGRADE_SETUP = "android.intent.action.UPGRADE_SETUP"; field public static final java.lang.String ACTION_USER_REMOVED = "android.intent.action.USER_REMOVED"; @@ -3447,6 +3445,7 @@ package android.os { field public static final java.lang.String ACTION_UPDATE_CT_LOGS = "android.intent.action.UPDATE_CT_LOGS"; field public static final java.lang.String ACTION_UPDATE_INTENT_FIREWALL = "android.intent.action.UPDATE_INTENT_FIREWALL"; field public static final java.lang.String ACTION_UPDATE_LANG_ID = "android.intent.action.UPDATE_LANG_ID"; + field public static final java.lang.String ACTION_UPDATE_NETWORK_WATCHLIST = "android.intent.action.UPDATE_NETWORK_WATCHLIST"; field public static final java.lang.String ACTION_UPDATE_PINS = "android.intent.action.UPDATE_PINS"; field public static final java.lang.String ACTION_UPDATE_SMART_SELECTION = "android.intent.action.UPDATE_SMART_SELECTION"; field public static final java.lang.String ACTION_UPDATE_SMS_SHORT_CODES = "android.intent.action.UPDATE_SMS_SHORT_CODES"; @@ -4526,6 +4525,9 @@ package android.telephony { method public int[] supplyPukReportResult(java.lang.String, java.lang.String); method public void toggleRadioOnOff(); method public void updateServiceLocation(); + field public static final java.lang.String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED"; + field public static final java.lang.String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED"; + field public static final java.lang.String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED"; field public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; // 0xfffffffe field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1 field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0 diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index 7a9588d1a2c4..7f0ebb45e2d7 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -86,6 +86,7 @@ message Atom { AppStartFullyDrawnChanged app_start_fully_drawn_changed = 50; LmkEventOccurred lmk_event_occurred = 51; PictureInPictureStateChanged picture_in_picture_state_changed = 52; + WifiMulticastLockStateChanged wifi_multicast_lock_state_changed = 53; // TODO: Reorder the numbering so that the most frequent occur events occur in the first 15. } @@ -707,6 +708,22 @@ message WifiScanStateChanged { } /** + * Logs wifi multicast locks held by an app + * + * Logged from: + * frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java + */ +message WifiMulticastLockStateChanged { + repeated AttributionNode attribution_node = 1; + + enum State { + OFF = 0; + ON = 1; + } + optional State state = 2; +} + +/** * Logs phone signal strength changes. * * Logged from: @@ -1322,4 +1339,4 @@ message SystemUptime { // for external input). // It is not affected by clock scaling, idle, or other power saving mechanisms. optional uint64 uptime_ms = 1; -}
\ No newline at end of file +} diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto index bb2193fb442b..f73c4a5303cf 100644 --- a/cmds/statsd/src/stats_log.proto +++ b/cmds/statsd/src/stats_log.proto @@ -188,78 +188,78 @@ message ConfigMetricsReportList { } message StatsdStatsReport { - optional int32 stats_begin_time_sec = 1; + optional int32 stats_begin_time_sec = 1; - optional int32 stats_end_time_sec = 2; + optional int32 stats_end_time_sec = 2; - message MatcherStats { - optional int64 id = 1; - optional int32 matched_times = 2; - } + message MatcherStats { + optional int64 id = 1; + optional int32 matched_times = 2; + } - message ConditionStats { - optional int64 id = 1; - optional int32 max_tuple_counts = 2; - } + message ConditionStats { + optional int64 id = 1; + optional int32 max_tuple_counts = 2; + } - message MetricStats { - optional int64 id = 1; - optional int32 max_tuple_counts = 2; - } + message MetricStats { + optional int64 id = 1; + optional int32 max_tuple_counts = 2; + } - message AlertStats { - optional int64 id = 1; - optional int32 alerted_times = 2; - } + message AlertStats { + optional int64 id = 1; + optional int32 alerted_times = 2; + } - message ConfigStats { - optional int32 uid = 1; - optional int64 id = 2; - optional int32 creation_time_sec = 3; - optional int32 deletion_time_sec = 4; - optional int32 metric_count = 5; - optional int32 condition_count = 6; - optional int32 matcher_count = 7; - optional int32 alert_count = 8; - optional bool is_valid = 9; - - repeated int32 broadcast_sent_time_sec = 10; - repeated int32 data_drop_time_sec = 11; - repeated int32 dump_report_time_sec = 12; - repeated MatcherStats matcher_stats = 13; - repeated ConditionStats condition_stats = 14; - repeated MetricStats metric_stats = 15; - repeated AlertStats alert_stats = 16; - } + message ConfigStats { + optional int32 uid = 1; + optional int64 id = 2; + optional int32 creation_time_sec = 3; + optional int32 deletion_time_sec = 4; + optional int32 metric_count = 5; + optional int32 condition_count = 6; + optional int32 matcher_count = 7; + optional int32 alert_count = 8; + optional bool is_valid = 9; + + repeated int32 broadcast_sent_time_sec = 10; + repeated int32 data_drop_time_sec = 11; + repeated int32 dump_report_time_sec = 12; + repeated MatcherStats matcher_stats = 13; + repeated ConditionStats condition_stats = 14; + repeated MetricStats metric_stats = 15; + repeated AlertStats alert_stats = 16; + } - repeated ConfigStats config_stats = 3; + repeated ConfigStats config_stats = 3; - message AtomStats { - optional int32 tag = 1; - optional int32 count = 2; - } + message AtomStats { + optional int32 tag = 1; + optional int32 count = 2; + } - repeated AtomStats atom_stats = 7; + repeated AtomStats atom_stats = 7; - message UidMapStats { - optional int32 snapshots = 1; - optional int32 changes = 2; - optional int32 bytes_used = 3; - optional int32 dropped_snapshots = 4; - optional int32 dropped_changes = 5; - } - optional UidMapStats uidmap_stats = 8; + message UidMapStats { + optional int32 snapshots = 1; + optional int32 changes = 2; + optional int32 bytes_used = 3; + optional int32 dropped_snapshots = 4; + optional int32 dropped_changes = 5; + } + optional UidMapStats uidmap_stats = 8; - message AnomalyAlarmStats { - optional int32 alarms_registered = 1; - } - optional AnomalyAlarmStats anomaly_alarm_stats = 9; + message AnomalyAlarmStats { + optional int32 alarms_registered = 1; + } + optional AnomalyAlarmStats anomaly_alarm_stats = 9; - message PulledAtomStats { - optional int32 atom_id = 1; - optional int64 total_pull = 2; - optional int64 total_pull_from_cache = 3; - optional int64 min_pull_interval_sec = 4; - } - repeated PulledAtomStats pulled_atom_stats = 10; + message PulledAtomStats { + optional int32 atom_id = 1; + optional int64 total_pull = 2; + optional int64 total_pull_from_cache = 3; + optional int64 min_pull_interval_sec = 4; + } + repeated PulledAtomStats pulled_atom_stats = 10; }
\ No newline at end of file diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto index cd60ee74e3ad..07bbcb2190e8 100644 --- a/cmds/statsd/src/statsd_config.proto +++ b/cmds/statsd/src/statsd_config.proto @@ -25,300 +25,303 @@ option java_outer_classname = "StatsdConfigProto"; import "frameworks/base/cmds/statsd/src/perfetto/perfetto_config.proto"; enum Position { - POSITION_UNKNOWN = 0; - FIRST = 1; - LAST = 2; - ANY = 3; + POSITION_UNKNOWN = 0; + + FIRST = 1; + + LAST = 2; + + ANY = 3; } enum TimeUnit { - TIME_UNIT_UNSPECIFIED = 0; - ONE_MINUTE = 1; - FIVE_MINUTES = 2; - TEN_MINUTES = 3; - THIRTY_MINUTES = 4; - ONE_HOUR = 5; - THREE_HOURS = 6; - SIX_HOURS = 7; - TWELVE_HOURS = 8; - ONE_DAY = 9; - CTS = 1000; + TIME_UNIT_UNSPECIFIED = 0; + ONE_MINUTE = 1; + FIVE_MINUTES = 2; + TEN_MINUTES = 3; + THIRTY_MINUTES = 4; + ONE_HOUR = 5; + THREE_HOURS = 6; + SIX_HOURS = 7; + TWELVE_HOURS = 8; + ONE_DAY = 9; + CTS = 1000; } message FieldMatcher { - optional int32 field = 1; + optional int32 field = 1; - optional Position position = 2; + optional Position position = 2; - repeated FieldMatcher child = 3; + repeated FieldMatcher child = 3; } message FieldValueMatcher { - // Field id, as specified in the atom proto message. - optional int32 field = 1; - - // For repeated fields, specifies the position in the array. - // FIRST and LAST mean that if the values are found at the first - // or last position, it's a match. ANY means that if the values are found - // anywhere in the array, then it's a match. - optional Position position = 2; - - oneof value_matcher { - bool eq_bool = 3; - string eq_string = 4; - int32 eq_int = 5; - - int64 lt_int = 6; - int64 gt_int = 7; - float lt_float = 8; - float gt_float = 9; - - int64 lte_int = 10; - int64 gte_int = 11; - - MessageMatcher matches_tuple = 12; - } + optional int32 field = 1; + + optional Position position = 2; + + oneof value_matcher { + bool eq_bool = 3; + string eq_string = 4; + int32 eq_int = 5; + + int64 lt_int = 6; + int64 gt_int = 7; + float lt_float = 8; + float gt_float = 9; + + int64 lte_int = 10; + int64 gte_int = 11; + + MessageMatcher matches_tuple = 12; + } } message MessageMatcher { - repeated FieldValueMatcher field_value_matcher = 1; + repeated FieldValueMatcher field_value_matcher = 1; } enum LogicalOperation { - LOGICAL_OPERATION_UNSPECIFIED = 0; - AND = 1; - OR = 2; - NOT = 3; - NAND = 4; - NOR = 5; + LOGICAL_OPERATION_UNSPECIFIED = 0; + AND = 1; + OR = 2; + NOT = 3; + NAND = 4; + NOR = 5; } message SimpleAtomMatcher { - optional int32 atom_id = 1; + optional int32 atom_id = 1; - repeated FieldValueMatcher field_value_matcher = 2; + repeated FieldValueMatcher field_value_matcher = 2; } message AtomMatcher { - optional int64 id = 1; + optional int64 id = 1; - message Combination { - optional LogicalOperation operation = 1; + message Combination { + optional LogicalOperation operation = 1; - repeated int64 matcher = 2; - } - oneof contents { - SimpleAtomMatcher simple_atom_matcher = 2; - Combination combination = 3; - } + repeated int64 matcher = 2; + } + oneof contents { + SimpleAtomMatcher simple_atom_matcher = 2; + Combination combination = 3; + } } message SimplePredicate { - optional int64 start = 1; + optional int64 start = 1; - optional int64 stop = 2; + optional int64 stop = 2; - optional bool count_nesting = 3 [default = true]; + optional bool count_nesting = 3 [default = true]; - optional int64 stop_all = 4; + optional int64 stop_all = 4; - enum InitialValue { - UNKNOWN = 0; - FALSE = 1; - } - optional InitialValue initial_value = 5 [default = FALSE]; + enum InitialValue { + UNKNOWN = 0; + FALSE = 1; + } + optional InitialValue initial_value = 5 [default = FALSE]; - optional FieldMatcher dimensions = 6; + optional FieldMatcher dimensions = 6; } message Predicate { - optional int64 id = 1; + optional int64 id = 1; - message Combination { - optional LogicalOperation operation = 1; + message Combination { + optional LogicalOperation operation = 1; - repeated int64 predicate = 2; - } + repeated int64 predicate = 2; + } - oneof contents { - SimplePredicate simple_predicate = 2; - Combination combination = 3; - } -} - -message Bucket { - optional int64 bucket_size_millis = 1; + oneof contents { + SimplePredicate simple_predicate = 2; + Combination combination = 3; + } } message MetricConditionLink { - optional int64 condition = 1; + optional int64 condition = 1; - optional FieldMatcher fields_in_what = 2; + optional FieldMatcher fields_in_what = 2; - optional FieldMatcher fields_in_condition = 3; + optional FieldMatcher fields_in_condition = 3; } message FieldFilter { - optional bool include_all = 1 [default = false]; - optional FieldMatcher fields = 2; + optional bool include_all = 1 [default = false]; + optional FieldMatcher fields = 2; } message EventMetric { - optional int64 id = 1; + optional int64 id = 1; - optional int64 what = 2; + optional int64 what = 2; - optional int64 condition = 3; + optional int64 condition = 3; - repeated MetricConditionLink links = 4; + repeated MetricConditionLink links = 4; } message CountMetric { - optional int64 id = 1; + optional int64 id = 1; - optional int64 what = 2; + optional int64 what = 2; - optional int64 condition = 3; + optional int64 condition = 3; - optional FieldMatcher dimensions_in_what = 4; + optional FieldMatcher dimensions_in_what = 4; - optional FieldMatcher dimensions_in_condition = 7; + optional FieldMatcher dimensions_in_condition = 7; - optional TimeUnit bucket = 5; + optional TimeUnit bucket = 5; - repeated MetricConditionLink links = 6; + repeated MetricConditionLink links = 6; } message DurationMetric { - optional int64 id = 1; + optional int64 id = 1; - optional int64 what = 2; + optional int64 what = 2; - optional int64 condition = 3; + optional int64 condition = 3; - repeated MetricConditionLink links = 4; + repeated MetricConditionLink links = 4; - enum AggregationType { - SUM = 1; + enum AggregationType { + SUM = 1; - MAX_SPARSE = 2; - } - optional AggregationType aggregation_type = 5 [default = SUM]; + MAX_SPARSE = 2; + } + optional AggregationType aggregation_type = 5 [default = SUM]; - optional FieldMatcher dimensions_in_what = 6; + optional FieldMatcher dimensions_in_what = 6; - optional FieldMatcher dimensions_in_condition = 8; + optional FieldMatcher dimensions_in_condition = 8; - optional TimeUnit bucket = 7; + optional TimeUnit bucket = 7; } message GaugeMetric { - optional int64 id = 1; + optional int64 id = 1; - optional int64 what = 2; + optional int64 what = 2; - optional FieldFilter gauge_fields_filter = 3; + optional FieldFilter gauge_fields_filter = 3; - optional int64 condition = 4; + optional int64 condition = 4; - optional FieldMatcher dimensions_in_what = 5; + optional FieldMatcher dimensions_in_what = 5; - optional FieldMatcher dimensions_in_condition = 8; + optional FieldMatcher dimensions_in_condition = 8; - optional TimeUnit bucket = 6; + optional TimeUnit bucket = 6; - repeated MetricConditionLink links = 7; + repeated MetricConditionLink links = 7; } message ValueMetric { - optional int64 id = 1; + optional int64 id = 1; - optional int64 what = 2; + optional int64 what = 2; - optional FieldMatcher value_field = 3; + optional FieldMatcher value_field = 3; - optional int64 condition = 4; + optional int64 condition = 4; - optional FieldMatcher dimensions_in_what = 5; + optional FieldMatcher dimensions_in_what = 5; - optional FieldMatcher dimensions_in_condition = 9; + optional FieldMatcher dimensions_in_condition = 9; - optional TimeUnit bucket = 6; + optional TimeUnit bucket = 6; - repeated MetricConditionLink links = 7; + repeated MetricConditionLink links = 7; - enum AggregationType { SUM = 1; } - optional AggregationType aggregation_type = 8 [default = SUM]; + enum AggregationType { + SUM = 1; + } + optional AggregationType aggregation_type = 8 [default = SUM]; } message Alert { - optional int64 id = 1; + optional int64 id = 1; - optional int64 metric_id = 2; + optional int64 metric_id = 2; - optional int32 num_buckets = 3; + optional int32 num_buckets = 3; - optional int32 refractory_period_secs = 4; + optional int32 refractory_period_secs = 4; - optional double trigger_if_sum_gt = 5; + optional double trigger_if_sum_gt = 5; } message Alarm { - optional int64 id = 1; - optional int64 offset_millis = 2; - optional int64 period_millis = 3; + optional int64 id = 1; + + optional int64 offset_millis = 2; + + optional int64 period_millis = 3; } message IncidentdDetails { - repeated int32 section = 1; + repeated int32 section = 1; } message PerfettoDetails { - optional perfetto.protos.TraceConfig trace_config = 1; + optional perfetto.protos.TraceConfig trace_config = 1; } -message Subscription { - optional int64 id = 1; - - enum RuleType { - RULE_TYPE_UNSPECIFIED = 0; - ALARM = 1; - ALERT = 2; - } - optional RuleType rule_type = 2; - - optional int64 rule_id = 3; +message BroadcastSubscriberDetails { + optional int64 subscriber_id = 1; +} - oneof subscriber_information { - IncidentdDetails incidentd_details = 4; - PerfettoDetails perfetto_details = 5; - } +message Subscription { + optional int64 id = 1; + + enum RuleType { + RULE_TYPE_UNSPECIFIED = 0; + ALARM = 1; + ALERT = 2; + } + optional RuleType rule_type = 2; + + optional int64 rule_id = 3; + + oneof subscriber_information { + IncidentdDetails incidentd_details = 4; + PerfettoDetails perfetto_details = 5; + BroadcastSubscriberDetails broadcast_subscriber_details = 6; + } } message StatsdConfig { - optional int64 id = 1; + optional int64 id = 1; - repeated EventMetric event_metric = 2; + repeated EventMetric event_metric = 2; - repeated CountMetric count_metric = 3; + repeated CountMetric count_metric = 3; - repeated ValueMetric value_metric = 4; + repeated ValueMetric value_metric = 4; - repeated GaugeMetric gauge_metric = 5; + repeated GaugeMetric gauge_metric = 5; - repeated DurationMetric duration_metric = 6; + repeated DurationMetric duration_metric = 6; - repeated AtomMatcher atom_matcher = 7; + repeated AtomMatcher atom_matcher = 7; - repeated Predicate predicate = 8; + repeated Predicate predicate = 8; - repeated Alert alert = 9; + repeated Alert alert = 9; - repeated Alarm alarm = 10; + repeated Alarm alarm = 10; - repeated Subscription subscription = 11; + repeated Subscription subscription = 11; - repeated string allowed_log_source = 12; + repeated string allowed_log_source = 12; - repeated int64 no_report_metric = 13; + repeated int64 no_report_metric = 13; } diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ConfigFactory.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ConfigFactory.java index 843b1e5f90ac..2e0161be8096 100644 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ConfigFactory.java +++ b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ConfigFactory.java @@ -19,7 +19,6 @@ import android.content.Context; import android.content.res.Resources; import android.util.Log; -import com.android.internal.os.StatsdConfigProto.Bucket; import com.android.internal.os.StatsdConfigProto.Predicate; import com.android.internal.os.StatsdConfigProto.CountMetric; import com.android.internal.os.StatsdConfigProto.DurationMetric; diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 4048e6596cfc..49d522440fc4 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -222,9 +222,18 @@ public class ApplicationPackageManager extends PackageManager { @Override public Intent getLeanbackLaunchIntentForPackage(String packageName) { - // Try to find a main leanback_launcher activity. + return getLaunchIntentForPackageAndCategory(packageName, Intent.CATEGORY_LEANBACK_LAUNCHER); + } + + @Override + public Intent getCarLaunchIntentForPackage(String packageName) { + return getLaunchIntentForPackageAndCategory(packageName, Intent.CATEGORY_CAR_LAUNCHER); + } + + private Intent getLaunchIntentForPackageAndCategory(String packageName, String category) { + // Try to find a main launcher activity for the given categories. Intent intentToResolve = new Intent(Intent.ACTION_MAIN); - intentToResolve.addCategory(Intent.CATEGORY_LEANBACK_LAUNCHER); + intentToResolve.addCategory(category); intentToResolve.setPackage(packageName); List<ResolveInfo> ris = queryIntentActivities(intentToResolve, 0); diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java index 8b76cc7c966b..d6429ae9e540 100644 --- a/core/java/android/app/PendingIntent.java +++ b/core/java/android/app/PendingIntent.java @@ -867,19 +867,30 @@ public final class PendingIntent implements Parcelable { @Nullable OnFinished onFinished, @Nullable Handler handler, @Nullable String requiredPermission, @Nullable Bundle options) throws CanceledException { + if (sendAndReturnResult(context, code, intent, onFinished, handler, requiredPermission, + options) < 0) { + throw new CanceledException(); + } + } + + /** + * Like {@link #send}, but returns the result + * @hide + */ + public int sendAndReturnResult(Context context, int code, @Nullable Intent intent, + @Nullable OnFinished onFinished, @Nullable Handler handler, + @Nullable String requiredPermission, @Nullable Bundle options) + throws CanceledException { try { String resolvedType = intent != null ? intent.resolveTypeIfNeeded(context.getContentResolver()) : null; - int res = ActivityManager.getService().sendIntentSender( + return ActivityManager.getService().sendIntentSender( mTarget, mWhitelistToken, code, intent, resolvedType, onFinished != null ? new FinishedDispatcher(this, onFinished, handler) : null, requiredPermission, options); - if (res < 0) { - throw new CanceledException(); - } } catch (RemoteException e) { throw new CanceledException(e); } diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java index 09c420c3e66a..2fa9d8e0882f 100644 --- a/core/java/android/app/slice/SliceManager.java +++ b/core/java/android/app/slice/SliceManager.java @@ -16,6 +16,7 @@ package android.app.slice; +import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemService; @@ -90,21 +91,21 @@ public class SliceManager { } /** - * Adds a callback to a specific slice uri. - * <p> - * This is a convenience that performs a few slice actions at once. It will put - * the slice in a pinned state since there is a callback attached. It will also - * listen for content changes, when a content change observes, the android system - * will bind the new slice and provide it to all registered {@link SliceCallback}s. - * - * @param uri The uri of the slice being listened to. - * @param callback The listener that should receive the callbacks. - * @param specs The list of supported {@link SliceSpec}s of the callback. - * @see SliceProvider#onSlicePinned(Uri) + * @deprecated TO BE REMOVED. */ + @Deprecated public void registerSliceCallback(@NonNull Uri uri, @NonNull SliceCallback callback, @NonNull List<SliceSpec> specs) { - registerSliceCallback(uri, callback, specs, Handler.getMain()); + registerSliceCallback(uri, specs, mContext.getMainExecutor(), callback); + } + + /** + * @deprecated TO BE REMOVED. + */ + @Deprecated + public void registerSliceCallback(@NonNull Uri uri, @NonNull SliceCallback callback, + @NonNull List<SliceSpec> specs, Executor executor) { + registerSliceCallback(uri, specs, executor, callback); } /** @@ -120,19 +121,9 @@ public class SliceManager { * @param specs The list of supported {@link SliceSpec}s of the callback. * @see SliceProvider#onSlicePinned(Uri) */ - public void registerSliceCallback(@NonNull Uri uri, @NonNull SliceCallback callback, - @NonNull List<SliceSpec> specs, Handler handler) { - try { - mService.addSliceListener(uri, mContext.getPackageName(), - getListener(uri, callback, new ISliceListener.Stub() { - @Override - public void onSliceUpdated(Slice s) throws RemoteException { - handler.post(() -> callback.onSliceUpdated(s)); - } - }), specs.toArray(new SliceSpec[specs.size()])); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + public void registerSliceCallback(@NonNull Uri uri, @NonNull List<SliceSpec> specs, + @NonNull SliceCallback callback) { + registerSliceCallback(uri, specs, mContext.getMainExecutor(), callback); } /** @@ -148,8 +139,8 @@ public class SliceManager { * @param specs The list of supported {@link SliceSpec}s of the callback. * @see SliceProvider#onSlicePinned(Uri) */ - public void registerSliceCallback(@NonNull Uri uri, @NonNull SliceCallback callback, - @NonNull List<SliceSpec> specs, Executor executor) { + public void registerSliceCallback(@NonNull Uri uri, @NonNull List<SliceSpec> specs, + @NonNull @CallbackExecutor Executor executor, @NonNull SliceCallback callback) { try { mService.addSliceListener(uri, mContext.getPackageName(), getListener(uri, callback, new ISliceListener.Stub() { diff --git a/core/java/android/app/slice/SliceProvider.java b/core/java/android/app/slice/SliceProvider.java index c4316a0ba086..bd4103f60ac6 100644 --- a/core/java/android/app/slice/SliceProvider.java +++ b/core/java/android/app/slice/SliceProvider.java @@ -89,7 +89,7 @@ import java.util.concurrent.CountDownLatch; */ public abstract class SliceProvider extends ContentProvider { /** - * This is the Android platform's MIME type for a slice: URI + * This is the Android platform's MIME type for a URI * containing a slice implemented through {@link SliceProvider}. */ public static final String SLICE_TYPE = "vnd.android.slice"; diff --git a/core/java/android/app/timezone/RulesState.java b/core/java/android/app/timezone/RulesState.java index 16309fab0924..e86d348a85fa 100644 --- a/core/java/android/app/timezone/RulesState.java +++ b/core/java/android/app/timezone/RulesState.java @@ -126,9 +126,6 @@ public final class RulesState implements Parcelable { mStagedOperationType == STAGED_OPERATION_INSTALL /* requireNotNull */, "stagedDistroRulesVersion", stagedDistroRulesVersion); - if (operationInProgress && distroStatus != DISTRO_STATUS_UNKNOWN) { - throw new IllegalArgumentException("distroInstalled != DISTRO_STATUS_UNKNOWN"); - } this.mDistroStatus = validateDistroStatus(distroStatus); this.mInstalledDistroRulesVersion = validateConditionalNull( mDistroStatus == DISTRO_STATUS_INSTALLED/* requireNotNull */, diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index f05a4d1aa9c7..acbdf142c62d 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -3525,74 +3525,6 @@ public class Intent implements Parcelable, Cloneable { public static final String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED"; /** - * Broadcast Action: The sim card state has changed. - * The intent will have the following extra values:</p> - * <dl> - * <dt>{@link android.telephony.TelephonyManager.EXTRA_SIM_STATE}</dt> - * <dd>The sim card state. One of: - * <dl> - * <dt>{@link android.telephony.TelephonyManager.SIM_STATE_ABSENT}</dt> - * <dd>SIM card not found</dd> - * <dt>{@link android.telephony.TelephonyManager.SIM_STATE_CARD_IO_ERROR}</dt> - * <dd>SIM card IO error</dd> - * <dt>{@link android.telephony.TelephonyManager.SIM_STATE_CARD_RESTRICTED}</dt> - * <dd>SIM card is restricted</dd> - * <dt>{@link android.telephony.TelephonyManager.SIM_STATE_PRESENT}</dt> - * <dd>SIM card is present</dd> - * </dl> - * </dd> - * </dl> - * - * <p class="note">Requires the READ_PRIVILEGED_PHONE_STATE permission. - * - * <p class="note">The current state can also be queried using - * {@link android.telephony.TelephonyManager.getSimCardState()} - * - * <p class="note">This is a protected intent that can only be sent by the system. - * @hide - */ - @SystemApi - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_SIM_CARD_STATE_CHANGED = - "android.intent.action.SIM_CARD_STATE_CHANGED"; - - /** - * Broadcast Action: The sim application state has changed. - * The intent will have the following extra values:</p> - * <dl> - * <dt>{@link android.telephony.TelephonyManager.EXTRA_SIM_STATE}</dt> - * <dd>The sim application state. One of: - * <dl> - * <dt>{@link android.telephony.TelephonyManager.SIM_STATE_NOT_READY}</dt> - * <dd>SIM card applications not ready</dd> - * <dt>{@link android.telephony.TelephonyManager.SIM_STATE_PIN_REQUIRED}</dt> - * <dd>SIM card PIN locked</dd> - * <dt>{@link android.telephony.TelephonyManager.SIM_STATE_PUK_REQUIRED}</dt> - * <dd>SIM card PUK locked</dd> - * <dt>{@link android.telephony.TelephonyManager.SIM_STATE_NETWORK_LOCKED}</dt> - * <dd>SIM card network locked</dd> - * <dt>{@link android.telephony.TelephonyManager.SIM_STATE_PERM_DISABLED}</dt> - * <dd>SIM card permanently disabled due to PUK failures</dd> - * <dt>{@link android.telephony.TelephonyManager.SIM_STATE_LOADED}</dt> - * <dd>SIM card data loaded</dd> - * </dl> - * </dd> - * </dl> - * - * <p class="note">Requires the READ_PRIVILEGED_PHONE_STATE permission. - * - * <p class="note">The current state can also be queried using - * {@link android.telephony.TelephonyManager.getSimApplicationState()} - * - * <p class="note">This is a protected intent that can only be sent by the system. - * @hide - */ - @SystemApi - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = - "android.intent.action.SIM_APPLICATION_STATE_CHANGED"; - - /** * Broadcast Action: indicate that the phone service state has changed. * The intent will have the following extra values:</p> * <p> @@ -3998,6 +3930,14 @@ public class Intent implements Parcelable, Cloneable { @SdkConstant(SdkConstantType.INTENT_CATEGORY) public static final String CATEGORY_LEANBACK_LAUNCHER = "android.intent.category.LEANBACK_LAUNCHER"; /** + * Indicates the preferred entry-point activity when an application is launched from a Car + * launcher. If not present, Car launcher can optionally use {@link #CATEGORY_LAUNCHER} as a + * fallback, or exclude the application entirely. + * @hide + */ + @SdkConstant(SdkConstantType.INTENT_CATEGORY) + public static final String CATEGORY_CAR_LAUNCHER = "android.intent.category.CAR_LAUNCHER"; + /** * Indicates a Leanback settings activity to be displayed in the Leanback launcher. * @hide */ diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index bcf80eeaaee7..b81267ab46f9 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -3044,6 +3044,21 @@ public abstract class PackageManager { public abstract @Nullable Intent getLeanbackLaunchIntentForPackage(@NonNull String packageName); /** + * Return a "good" intent to launch a front-door Car activity in a + * package, for use for example to implement an "open" button when browsing + * through packages. The current implementation will look for a main + * activity in the category {@link Intent#CATEGORY_CAR_LAUNCHER}, or + * return null if no main car activities are found. + * + * @param packageName The name of the package to inspect. + * @return Returns either a fully-qualified Intent that can be used to launch + * the main Car activity in the package, or null if the package + * does not contain such an activity. + * @hide + */ + public abstract @Nullable Intent getCarLaunchIntentForPackage(@NonNull String packageName); + + /** * Return an array of all of the POSIX secondary group IDs that have been * assigned to the given package. * <p> diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 11d338d05c68..166342dd4e6d 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -3763,4 +3763,20 @@ public class ConnectivityManager { throw e.rethrowFromSystemServer(); } } + + /** + * The network watchlist is a list of domains and IP addresses that are associated with + * potentially harmful apps. This method returns the hash of the watchlist currently + * used by the system. + * + * @return Hash of network watchlist config file. Null if config does not exist. + */ + public byte[] getNetworkWatchlistConfigHash() { + try { + return mService.getNetworkWatchlistConfigHash(); + } catch (RemoteException e) { + Log.e(TAG, "Unable to get watchlist config hash"); + throw e.rethrowFromSystemServer(); + } + } } diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index a6fe7389bc72..ce95b60dd2db 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -180,4 +180,6 @@ interface IConnectivityManager void stopKeepalive(in Network network, int slot); String getCaptivePortalServerUrl(); + + byte[] getNetworkWatchlistConfigHash(); } diff --git a/core/java/android/net/NetworkWatchlistManager.java b/core/java/android/net/NetworkWatchlistManager.java index 5425bf534ebd..49047d3a0c87 100644 --- a/core/java/android/net/NetworkWatchlistManager.java +++ b/core/java/android/net/NetworkWatchlistManager.java @@ -86,4 +86,16 @@ public class NetworkWatchlistManager { e.rethrowFromSystemServer(); } } + + /** + * Get Network Watchlist config file hash. + */ + public byte[] getWatchlistConfigHash() { + try { + return mNetworkWatchlistManager.getWatchlistConfigHash(); + } catch (RemoteException e) { + Log.e(TAG, "Unable to get watchlist config hash"); + throw e.rethrowFromSystemServer(); + } + } } diff --git a/core/java/android/os/ConfigUpdate.java b/core/java/android/os/ConfigUpdate.java index 94a44ec3729a..dda0ed8a5e20 100644 --- a/core/java/android/os/ConfigUpdate.java +++ b/core/java/android/os/ConfigUpdate.java @@ -82,6 +82,14 @@ public final class ConfigUpdate { public static final String ACTION_UPDATE_SMART_SELECTION = "android.intent.action.UPDATE_SMART_SELECTION"; + /** + * Update network watchlist config file. + * @hide + */ + @SystemApi + public static final String ACTION_UPDATE_NETWORK_WATCHLIST + = "android.intent.action.UPDATE_NETWORK_WATCHLIST"; + private ConfigUpdate() { } } diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 7654e9b6ee22..76838807acc5 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -143,7 +143,7 @@ public class Process { * Defines the UID/GID for the WebView zygote process. * @hide */ - public static final int WEBVIEW_ZYGOTE_UID = 1051; + public static final int WEBVIEW_ZYGOTE_UID = 1053; /** * Defines the UID used for resource tracking for OTA updates. diff --git a/core/java/android/security/keystore/BackwardsCompat.java b/core/java/android/security/keystore/BackwardsCompat.java new file mode 100644 index 000000000000..24921f03f136 --- /dev/null +++ b/core/java/android/security/keystore/BackwardsCompat.java @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.keystore; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +/** + * Helpers for converting classes between old and new API, so we can preserve backwards + * compatibility while teamfooding. This will be removed soon. + * + * @hide + */ +class BackwardsCompat { + + + static KeychainProtectionParams toLegacyKeychainProtectionParams( + android.security.keystore.recovery.KeychainProtectionParams keychainProtectionParams + ) { + return new KeychainProtectionParams.Builder() + .setUserSecretType(keychainProtectionParams.getUserSecretType()) + .setSecret(keychainProtectionParams.getSecret()) + .setLockScreenUiFormat(keychainProtectionParams.getLockScreenUiFormat()) + .setKeyDerivationParams( + toLegacyKeyDerivationParams( + keychainProtectionParams.getKeyDerivationParams())) + .build(); + } + + static KeyDerivationParams toLegacyKeyDerivationParams( + android.security.keystore.recovery.KeyDerivationParams keyDerivationParams + ) { + return new KeyDerivationParams( + keyDerivationParams.getAlgorithm(), keyDerivationParams.getSalt()); + } + + static WrappedApplicationKey toLegacyWrappedApplicationKey( + android.security.keystore.recovery.WrappedApplicationKey wrappedApplicationKey + ) { + return new WrappedApplicationKey.Builder() + .setAlias(wrappedApplicationKey.getAlias()) + .setEncryptedKeyMaterial(wrappedApplicationKey.getEncryptedKeyMaterial()) + .build(); + } + + static android.security.keystore.recovery.KeyDerivationParams fromLegacyKeyDerivationParams( + KeyDerivationParams keyDerivationParams + ) { + return new android.security.keystore.recovery.KeyDerivationParams( + keyDerivationParams.getAlgorithm(), keyDerivationParams.getSalt()); + } + + static android.security.keystore.recovery.WrappedApplicationKey fromLegacyWrappedApplicationKey( + WrappedApplicationKey wrappedApplicationKey + ) { + return new android.security.keystore.recovery.WrappedApplicationKey.Builder() + .setAlias(wrappedApplicationKey.getAlias()) + .setEncryptedKeyMaterial(wrappedApplicationKey.getEncryptedKeyMaterial()) + .build(); + } + + static List<android.security.keystore.recovery.WrappedApplicationKey> + fromLegacyWrappedApplicationKeys(List<WrappedApplicationKey> wrappedApplicationKeys + ) { + return map(wrappedApplicationKeys, BackwardsCompat::fromLegacyWrappedApplicationKey); + } + + static List<android.security.keystore.recovery.KeychainProtectionParams> + fromLegacyKeychainProtectionParams( + List<KeychainProtectionParams> keychainProtectionParams) { + return map(keychainProtectionParams, BackwardsCompat::fromLegacyKeychainProtectionParam); + } + + static android.security.keystore.recovery.KeychainProtectionParams + fromLegacyKeychainProtectionParam(KeychainProtectionParams keychainProtectionParams) { + return new android.security.keystore.recovery.KeychainProtectionParams.Builder() + .setUserSecretType(keychainProtectionParams.getUserSecretType()) + .setSecret(keychainProtectionParams.getSecret()) + .setLockScreenUiFormat(keychainProtectionParams.getLockScreenUiFormat()) + .setKeyDerivationParams( + fromLegacyKeyDerivationParams( + keychainProtectionParams.getKeyDerivationParams())) + .build(); + } + + static KeychainSnapshot toLegacyKeychainSnapshot( + android.security.keystore.recovery.KeychainSnapshot keychainSnapshot + ) { + return new KeychainSnapshot.Builder() + .setCounterId(keychainSnapshot.getCounterId()) + .setEncryptedRecoveryKeyBlob(keychainSnapshot.getEncryptedRecoveryKeyBlob()) + .setTrustedHardwarePublicKey(keychainSnapshot.getTrustedHardwarePublicKey()) + .setSnapshotVersion(keychainSnapshot.getSnapshotVersion()) + .setMaxAttempts(keychainSnapshot.getMaxAttempts()) + .setServerParams(keychainSnapshot.getServerParams()) + .setKeychainProtectionParams( + map(keychainSnapshot.getKeychainProtectionParams(), + BackwardsCompat::toLegacyKeychainProtectionParams)) + .setWrappedApplicationKeys( + map(keychainSnapshot.getWrappedApplicationKeys(), + BackwardsCompat::toLegacyWrappedApplicationKey)) + .build(); + } + + static <A, B> List<B> map(List<A> as, Function<A, B> f) { + ArrayList<B> bs = new ArrayList<>(as.size()); + for (A a : as) { + bs.add(f.apply(a)); + } + return bs; + } +} diff --git a/core/java/android/security/keystore/KeyDerivationParams.java b/core/java/android/security/keystore/KeyDerivationParams.java index b702accffba1..b19cee2d31a4 100644 --- a/core/java/android/security/keystore/KeyDerivationParams.java +++ b/core/java/android/security/keystore/KeyDerivationParams.java @@ -61,7 +61,7 @@ public final class KeyDerivationParams implements Parcelable { return new KeyDerivationParams(ALGORITHM_SHA256, salt); } - private KeyDerivationParams(@KeyDerivationAlgorithm int algorithm, @NonNull byte[] salt) { + KeyDerivationParams(@KeyDerivationAlgorithm int algorithm, @NonNull byte[] salt) { mAlgorithm = algorithm; mSalt = Preconditions.checkNotNull(salt); } diff --git a/core/java/android/security/keystore/RecoveryController.java b/core/java/android/security/keystore/RecoveryController.java index 87283cbd75ab..8be6d5263c53 100644 --- a/core/java/android/security/keystore/RecoveryController.java +++ b/core/java/android/security/keystore/RecoveryController.java @@ -167,7 +167,7 @@ public class RecoveryController { public @NonNull KeychainSnapshot getRecoveryData(@NonNull byte[] account) throws InternalRecoveryServiceException { try { - return mBinder.getRecoveryData(account); + return BackwardsCompat.toLegacyKeychainSnapshot(mBinder.getRecoveryData(account)); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { @@ -360,28 +360,6 @@ public class RecoveryController { } /** - * Method notifies KeyStore that a user-generated secret is available. This method generates a - * symmetric session key which a trusted remote device can use to return a recovery key. Caller - * should use {@link KeychainProtectionParams#clearSecret} to override the secret value in - * memory. - * - * @param recoverySecret user generated secret together with parameters necessary to regenerate - * it on a new device. - * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery - * service. - */ - public void recoverySecretAvailable(@NonNull KeychainProtectionParams recoverySecret) - throws InternalRecoveryServiceException { - try { - mBinder.recoverySecretAvailable(recoverySecret); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } catch (ServiceSpecificException e) { - throw wrapUnexpectedServiceSpecificException(e); - } - } - - /** * Initializes recovery session and returns a blob with proof of recovery secrets possession. * The method generates symmetric key for a session, which trusted remote device can use to * return recovery key. @@ -417,7 +395,7 @@ public class RecoveryController { verifierPublicKey, vaultParams, vaultChallenge, - secrets); + BackwardsCompat.fromLegacyKeychainProtectionParams(secrets)); return new RecoveryClaim(recoverySession, recoveryClaim); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -451,7 +429,9 @@ public class RecoveryController { InternalRecoveryServiceException { try { return (Map<String, byte[]>) mBinder.recoverKeys( - session.getSessionId(), recoveryKeyBlob, applicationKeys); + session.getSessionId(), + recoveryKeyBlob, + BackwardsCompat.fromLegacyWrappedApplicationKeys(applicationKeys)); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { diff --git a/core/java/android/security/keystore/recovery/BadCertificateFormatException.java b/core/java/android/security/keystore/recovery/BadCertificateFormatException.java new file mode 100644 index 000000000000..fda3387bb63b --- /dev/null +++ b/core/java/android/security/keystore/recovery/BadCertificateFormatException.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.keystore.recovery; + +/** + * Error thrown when the recovery agent supplies an invalid X509 certificate. + * + * @hide + */ +public class BadCertificateFormatException extends RecoveryControllerException { + public BadCertificateFormatException(String msg) { + super(msg); + } +} diff --git a/core/java/android/security/keystore/recovery/DecryptionFailedException.java b/core/java/android/security/keystore/recovery/DecryptionFailedException.java new file mode 100644 index 000000000000..b414dc59834b --- /dev/null +++ b/core/java/android/security/keystore/recovery/DecryptionFailedException.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.keystore.recovery; + +/** + * Error thrown when decryption failed, due to an agent error. i.e., using the incorrect key, + * trying to decrypt garbage data, trying to decrypt data that has somehow been corrupted, etc. + * + * @hide + */ +public class DecryptionFailedException extends RecoveryControllerException { + + public DecryptionFailedException(String msg) { + super(msg); + } +} diff --git a/core/java/android/security/keystore/recovery/InternalRecoveryServiceException.java b/core/java/android/security/keystore/recovery/InternalRecoveryServiceException.java new file mode 100644 index 000000000000..07a540ceea25 --- /dev/null +++ b/core/java/android/security/keystore/recovery/InternalRecoveryServiceException.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.keystore.recovery; + +/** + * An error thrown when something went wrong internally in the recovery service. + * + * <p>This is an unexpected error, and indicates a problem with the service itself, rather than the + * caller having performed some kind of illegal action. + * + * @hide + */ +public class InternalRecoveryServiceException extends RecoveryControllerException { + public InternalRecoveryServiceException(String msg) { + super(msg); + } + + public InternalRecoveryServiceException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/core/java/android/security/keystore/KeyDerivationParams.aidl b/core/java/android/security/keystore/recovery/KeyDerivationParams.aidl index f39aa047adee..2b1bbbe35f1a 100644 --- a/core/java/android/security/keystore/KeyDerivationParams.aidl +++ b/core/java/android/security/keystore/recovery/KeyDerivationParams.aidl @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.security.keystore; +package android.security.keystore.recovery; /* @hide */ parcelable KeyDerivationParams; diff --git a/core/java/android/security/keystore/recovery/KeyDerivationParams.java b/core/java/android/security/keystore/recovery/KeyDerivationParams.java new file mode 100644 index 000000000000..90613952ae9b --- /dev/null +++ b/core/java/android/security/keystore/recovery/KeyDerivationParams.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 android.security.keystore.recovery; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.os.Parcel; +import android.os.Parcelable; + +import com.android.internal.util.Preconditions; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Collection of parameters which define a key derivation function. + * Currently only supports salted SHA-256 + * + * @hide + */ +public final class KeyDerivationParams implements Parcelable { + private final int mAlgorithm; + private byte[] mSalt; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"ALGORITHM_"}, value = {ALGORITHM_SHA256, ALGORITHM_ARGON2ID}) + public @interface KeyDerivationAlgorithm { + } + + /** + * Salted SHA256 + */ + public static final int ALGORITHM_SHA256 = 1; + + /** + * Argon2ID + * @hide + */ + // TODO: add Argon2ID support. + public static final int ALGORITHM_ARGON2ID = 2; + + /** + * Creates instance of the class to to derive key using salted SHA256 hash. + */ + public static KeyDerivationParams createSha256Params(@NonNull byte[] salt) { + return new KeyDerivationParams(ALGORITHM_SHA256, salt); + } + + // TODO: Make private once legacy API is removed + public KeyDerivationParams(@KeyDerivationAlgorithm int algorithm, @NonNull byte[] salt) { + mAlgorithm = algorithm; + mSalt = Preconditions.checkNotNull(salt); + } + + /** + * Gets algorithm. + */ + public @KeyDerivationAlgorithm int getAlgorithm() { + return mAlgorithm; + } + + /** + * Gets salt. + */ + public @NonNull byte[] getSalt() { + return mSalt; + } + + public static final Creator<KeyDerivationParams> CREATOR = + new Creator<KeyDerivationParams>() { + public KeyDerivationParams createFromParcel(Parcel in) { + return new KeyDerivationParams(in); + } + + public KeyDerivationParams[] newArray(int length) { + return new KeyDerivationParams[length]; + } + }; + + /** + * @hide + */ + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeInt(mAlgorithm); + out.writeByteArray(mSalt); + } + + /** + * @hide + */ + protected KeyDerivationParams(Parcel in) { + mAlgorithm = in.readInt(); + mSalt = in.createByteArray(); + } + + @Override + public int describeContents() { + return 0; + } +} diff --git a/core/java/android/security/keystore/KeychainProtectionParams.aidl b/core/java/android/security/keystore/recovery/KeychainProtectionParams.aidl index 0341223b081a..538573847b00 100644 --- a/core/java/android/security/keystore/KeychainProtectionParams.aidl +++ b/core/java/android/security/keystore/recovery/KeychainProtectionParams.aidl @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.security.keystore; +package android.security.keystore.recovery; /* @hide */ parcelable KeychainProtectionParams; diff --git a/core/java/android/security/keystore/recovery/KeychainProtectionParams.java b/core/java/android/security/keystore/recovery/KeychainProtectionParams.java new file mode 100644 index 000000000000..445815b48e7c --- /dev/null +++ b/core/java/android/security/keystore/recovery/KeychainProtectionParams.java @@ -0,0 +1,289 @@ +/* + * 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.security.keystore.recovery; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.os.Parcel; +import android.os.Parcelable; + +import com.android.internal.util.Preconditions; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Arrays; + +/** + * A {@link KeychainSnapshot} is protected with a key derived from the user's lock screen. This + * class wraps all the data necessary to derive the same key on a recovering device: + * + * <ul> + * <li>UI parameters for the user's lock screen - so that if e.g., the user was using a pattern, + * the recovering device can display the pattern UI to the user when asking them to enter + * the lock screen from their previous device. + * <li>The algorithm used to derive a key from the user's lock screen, e.g. SHA-256 with a salt. + * </ul> + * + * <p>As such, this data is sent along with the {@link KeychainSnapshot} when syncing the current + * version of the keychain. + * + * <p>For now, the recoverable keychain only supports a single layer of protection, which is the + * user's lock screen. In the future, the keychain will support multiple layers of protection + * (e.g. an additional keychain password, along with the lock screen). + * + * @hide + */ +public final class KeychainProtectionParams implements Parcelable { + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({TYPE_LOCKSCREEN, TYPE_CUSTOM_PASSWORD}) + public @interface UserSecretType { + } + + /** + * Lockscreen secret is required to recover KeyStore. + */ + public static final int TYPE_LOCKSCREEN = 100; + + /** + * Custom passphrase, unrelated to lock screen, is required to recover KeyStore. + */ + public static final int TYPE_CUSTOM_PASSWORD = 101; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({TYPE_PIN, TYPE_PASSWORD, TYPE_PATTERN}) + public @interface LockScreenUiFormat { + } + + /** + * Pin with digits only. + */ + public static final int TYPE_PIN = 1; + + /** + * Password. String with latin-1 characters only. + */ + public static final int TYPE_PASSWORD = 2; + + /** + * Pattern with 3 by 3 grid. + */ + public static final int TYPE_PATTERN = 3; + + @UserSecretType + private Integer mUserSecretType; + + @LockScreenUiFormat + private Integer mLockScreenUiFormat; + + /** + * Parameters of the key derivation function, including algorithm, difficulty, salt. + */ + private KeyDerivationParams mKeyDerivationParams; + private byte[] mSecret; // Derived from user secret. The field must have limited visibility. + + /** + * @param secret Constructor creates a reference to the secret. Caller must use + * @link {#clearSecret} to overwrite its value in memory. + * @hide + */ + public KeychainProtectionParams(@UserSecretType int userSecretType, + @LockScreenUiFormat int lockScreenUiFormat, + @NonNull KeyDerivationParams keyDerivationParams, + @NonNull byte[] secret) { + mUserSecretType = userSecretType; + mLockScreenUiFormat = lockScreenUiFormat; + mKeyDerivationParams = Preconditions.checkNotNull(keyDerivationParams); + mSecret = Preconditions.checkNotNull(secret); + } + + private KeychainProtectionParams() { + + } + + /** + * @see TYPE_LOCKSCREEN + * @see TYPE_CUSTOM_PASSWORD + */ + public @UserSecretType int getUserSecretType() { + return mUserSecretType; + } + + /** + * Specifies UX shown to user during recovery. + * Default value is {@code TYPE_LOCKSCREEN} + * + * @see TYPE_PIN + * @see TYPE_PASSWORD + * @see TYPE_PATTERN + */ + public @LockScreenUiFormat int getLockScreenUiFormat() { + return mLockScreenUiFormat; + } + + /** + * Specifies function used to derive symmetric key from user input + * Format is defined in separate util class. + */ + @NonNull public KeyDerivationParams getKeyDerivationParams() { + return mKeyDerivationParams; + } + + /** + * Secret derived from user input. + * Default value is empty array + * + * @return secret or empty array + */ + public @NonNull byte[] getSecret() { + return mSecret; + } + + /** + * Builder for creating {@link KeychainProtectionParams}. + */ + public static class Builder { + private KeychainProtectionParams + mInstance = new KeychainProtectionParams(); + + /** + * Sets user secret type. + * + * @see TYPE_LOCKSCREEN + * @see TYPE_CUSTOM_PASSWORD + * @param userSecretType The secret type + * @return This builder. + */ + public Builder setUserSecretType(@UserSecretType int userSecretType) { + mInstance.mUserSecretType = userSecretType; + return this; + } + + /** + * Sets UI format. + * + * @see TYPE_PIN + * @see TYPE_PASSWORD + * @see TYPE_PATTERN + * @param lockScreenUiFormat The UI format + * @return This builder. + */ + public Builder setLockScreenUiFormat(@LockScreenUiFormat int lockScreenUiFormat) { + mInstance.mLockScreenUiFormat = lockScreenUiFormat; + return this; + } + + /** + * Sets parameters of the key derivation function. + * + * @param keyDerivationParams Key derivation Params + * @return This builder. + */ + public Builder setKeyDerivationParams(@NonNull KeyDerivationParams + keyDerivationParams) { + mInstance.mKeyDerivationParams = keyDerivationParams; + return this; + } + + /** + * Secret derived from user input, or empty array. + * + * @param secret The secret. + * @return This builder. + */ + public Builder setSecret(@NonNull byte[] secret) { + mInstance.mSecret = secret; + return this; + } + + + /** + * Creates a new {@link KeychainProtectionParams} instance. + * The instance will include default values, if {@link setSecret} + * or {@link setUserSecretType} were not called. + * + * @return new instance + * @throws NullPointerException if some required fields were not set. + */ + @NonNull public KeychainProtectionParams build() { + if (mInstance.mUserSecretType == null) { + mInstance.mUserSecretType = TYPE_LOCKSCREEN; + } + Preconditions.checkNotNull(mInstance.mLockScreenUiFormat); + Preconditions.checkNotNull(mInstance.mKeyDerivationParams); + if (mInstance.mSecret == null) { + mInstance.mSecret = new byte[]{}; + } + return mInstance; + } + } + + /** + * Removes secret from memory than object is no longer used. + * Since finalizer call is not reliable, please use @link {#clearSecret} directly. + */ + @Override + protected void finalize() throws Throwable { + clearSecret(); + super.finalize(); + } + + /** + * Fills mSecret with zeroes. + */ + public void clearSecret() { + Arrays.fill(mSecret, (byte) 0); + } + + public static final Creator<KeychainProtectionParams> CREATOR = + new Creator<KeychainProtectionParams>() { + public KeychainProtectionParams createFromParcel(Parcel in) { + return new KeychainProtectionParams(in); + } + + public KeychainProtectionParams[] newArray(int length) { + return new KeychainProtectionParams[length]; + } + }; + + /** + * @hide + */ + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeInt(mUserSecretType); + out.writeInt(mLockScreenUiFormat); + out.writeTypedObject(mKeyDerivationParams, flags); + out.writeByteArray(mSecret); + } + + /** + * @hide + */ + protected KeychainProtectionParams(Parcel in) { + mUserSecretType = in.readInt(); + mLockScreenUiFormat = in.readInt(); + mKeyDerivationParams = in.readTypedObject(KeyDerivationParams.CREATOR); + mSecret = in.createByteArray(); + } + + @Override + public int describeContents() { + return 0; + } +} diff --git a/core/java/android/security/keystore/KeychainSnapshot.aidl b/core/java/android/security/keystore/recovery/KeychainSnapshot.aidl index b35713f329d6..7822f39bf269 100644 --- a/core/java/android/security/keystore/KeychainSnapshot.aidl +++ b/core/java/android/security/keystore/recovery/KeychainSnapshot.aidl @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.security.keystore; +package android.security.keystore.recovery; /* @hide */ parcelable KeychainSnapshot; diff --git a/core/java/android/security/keystore/recovery/KeychainSnapshot.java b/core/java/android/security/keystore/recovery/KeychainSnapshot.java new file mode 100644 index 000000000000..a8e2725c0339 --- /dev/null +++ b/core/java/android/security/keystore/recovery/KeychainSnapshot.java @@ -0,0 +1,300 @@ +/* + * 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.security.keystore.recovery; + +import android.annotation.NonNull; +import android.os.Parcel; +import android.os.Parcelable; + +import com.android.internal.util.Preconditions; + +import java.util.List; + +/** + * A snapshot of a version of the keystore. Two events can trigger the generation of a new snapshot: + * + * <ul> + * <li>The user's lock screen changes. (A key derived from the user's lock screen is used to + * protected the keychain, which is why this forces a new snapshot.) + * <li>A key is added to or removed from the recoverable keychain. + * </ul> + * + * <p>The snapshot data is also encrypted with the remote trusted hardware's public key, so even + * the recovery agent itself should not be able to decipher the data. The recovery agent sends an + * instance of this to the remote trusted hardware whenever a new snapshot is generated. During a + * recovery flow, the recovery agent retrieves a snapshot from the remote trusted hardware. It then + * sends it to the framework, where it is decrypted using the user's lock screen from their previous + * device. + * + * @hide + */ +public final class KeychainSnapshot implements Parcelable { + private static final int DEFAULT_MAX_ATTEMPTS = 10; + private static final long DEFAULT_COUNTER_ID = 1L; + + private int mSnapshotVersion; + private int mMaxAttempts = DEFAULT_MAX_ATTEMPTS; + private long mCounterId = DEFAULT_COUNTER_ID; + private byte[] mServerParams; + private byte[] mPublicKey; + private List<KeychainProtectionParams> mKeychainProtectionParams; + private List<WrappedApplicationKey> mEntryRecoveryData; + private byte[] mEncryptedRecoveryKeyBlob; + + /** + * @hide + * Deprecated, consider using builder. + */ + public KeychainSnapshot( + int snapshotVersion, + @NonNull List<KeychainProtectionParams> keychainProtectionParams, + @NonNull List<WrappedApplicationKey> wrappedApplicationKeys, + @NonNull byte[] encryptedRecoveryKeyBlob) { + mSnapshotVersion = snapshotVersion; + mKeychainProtectionParams = + Preconditions.checkCollectionElementsNotNull(keychainProtectionParams, + "keychainProtectionParams"); + mEntryRecoveryData = Preconditions.checkCollectionElementsNotNull(wrappedApplicationKeys, + "wrappedApplicationKeys"); + mEncryptedRecoveryKeyBlob = Preconditions.checkNotNull(encryptedRecoveryKeyBlob); + } + + private KeychainSnapshot() { + + } + + /** + * Snapshot version for given account. It is incremented when user secret or list of application + * keys changes. + */ + public int getSnapshotVersion() { + return mSnapshotVersion; + } + + /** + * Number of user secret guesses allowed during Keychain recovery. + */ + public int getMaxAttempts() { + return mMaxAttempts; + } + + /** + * CounterId which is rotated together with user secret. + */ + public long getCounterId() { + return mCounterId; + } + + /** + * Server parameters. + */ + public @NonNull byte[] getServerParams() { + return mServerParams; + } + + /** + * Public key used to encrypt {@code encryptedRecoveryKeyBlob}. + * + * See implementation for binary key format + */ + // TODO: document key format. + public @NonNull byte[] getTrustedHardwarePublicKey() { + return mPublicKey; + } + + /** + * UI and key derivation parameters. Note that combination of secrets may be used. + */ + public @NonNull List<KeychainProtectionParams> getKeychainProtectionParams() { + return mKeychainProtectionParams; + } + + /** + * List of application keys, with key material encrypted by + * the recovery key ({@link #getEncryptedRecoveryKeyBlob}). + */ + public @NonNull List<WrappedApplicationKey> getWrappedApplicationKeys() { + return mEntryRecoveryData; + } + + /** + * Recovery key blob, encrypted by user secret and recovery service public key. + */ + public @NonNull byte[] getEncryptedRecoveryKeyBlob() { + return mEncryptedRecoveryKeyBlob; + } + + public static final Creator<KeychainSnapshot> CREATOR = + new Creator<KeychainSnapshot>() { + public KeychainSnapshot createFromParcel(Parcel in) { + return new KeychainSnapshot(in); + } + + public KeychainSnapshot[] newArray(int length) { + return new KeychainSnapshot[length]; + } + }; + + /** + * Builder for creating {@link KeychainSnapshot}. + */ + public static class Builder { + private KeychainSnapshot + mInstance = new KeychainSnapshot(); + + /** + * Snapshot version for given account. + * + * @param snapshotVersion The snapshot version + * @return This builder. + */ + public Builder setSnapshotVersion(int snapshotVersion) { + mInstance.mSnapshotVersion = snapshotVersion; + return this; + } + + /** + * Sets the number of user secret guesses allowed during Keychain recovery. + * + * @param maxAttempts The maximum number of guesses. + * @return This builder. + */ + public Builder setMaxAttempts(int maxAttempts) { + mInstance.mMaxAttempts = maxAttempts; + return this; + } + + /** + * Sets counter id. + * + * @param counterId The counter id. + * @return This builder. + */ + public Builder setCounterId(long counterId) { + mInstance.mCounterId = counterId; + return this; + } + + /** + * Sets server parameters. + * + * @param serverParams The server parameters + * @return This builder. + */ + public Builder setServerParams(byte[] serverParams) { + mInstance.mServerParams = serverParams; + return this; + } + + /** + * Sets public key used to encrypt recovery blob. + * + * @param publicKey The public key + * @return This builder. + */ + public Builder setTrustedHardwarePublicKey(byte[] publicKey) { + mInstance.mPublicKey = publicKey; + return this; + } + + /** + * Sets UI and key derivation parameters + * + * @param recoveryMetadata The UI and key derivation parameters + * @return This builder. + */ + public Builder setKeychainProtectionParams( + @NonNull List<KeychainProtectionParams> recoveryMetadata) { + mInstance.mKeychainProtectionParams = recoveryMetadata; + return this; + } + + /** + * List of application keys. + * + * @param entryRecoveryData List of application keys + * @return This builder. + */ + public Builder setWrappedApplicationKeys(List<WrappedApplicationKey> entryRecoveryData) { + mInstance.mEntryRecoveryData = entryRecoveryData; + return this; + } + + /** + * Sets recovery key blob + * + * @param encryptedRecoveryKeyBlob The recovery key blob. + * @return This builder. + */ + public Builder setEncryptedRecoveryKeyBlob(@NonNull byte[] encryptedRecoveryKeyBlob) { + mInstance.mEncryptedRecoveryKeyBlob = encryptedRecoveryKeyBlob; + return this; + } + + + /** + * Creates a new {@link KeychainSnapshot} instance. + * + * @return new instance + * @throws NullPointerException if some required fields were not set. + */ + @NonNull public KeychainSnapshot build() { + Preconditions.checkCollectionElementsNotNull(mInstance.mKeychainProtectionParams, + "recoveryMetadata"); + Preconditions.checkCollectionElementsNotNull(mInstance.mEntryRecoveryData, + "entryRecoveryData"); + Preconditions.checkNotNull(mInstance.mEncryptedRecoveryKeyBlob); + Preconditions.checkNotNull(mInstance.mServerParams); + Preconditions.checkNotNull(mInstance.mPublicKey); + return mInstance; + } + } + + /** + * @hide + */ + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeInt(mSnapshotVersion); + out.writeTypedList(mKeychainProtectionParams); + out.writeByteArray(mEncryptedRecoveryKeyBlob); + out.writeTypedList(mEntryRecoveryData); + out.writeInt(mMaxAttempts); + out.writeLong(mCounterId); + out.writeByteArray(mServerParams); + out.writeByteArray(mPublicKey); + } + + /** + * @hide + */ + protected KeychainSnapshot(Parcel in) { + mSnapshotVersion = in.readInt(); + mKeychainProtectionParams = in.createTypedArrayList(KeychainProtectionParams.CREATOR); + mEncryptedRecoveryKeyBlob = in.createByteArray(); + mEntryRecoveryData = in.createTypedArrayList(WrappedApplicationKey.CREATOR); + mMaxAttempts = in.readInt(); + mCounterId = in.readLong(); + mServerParams = in.createByteArray(); + mPublicKey = in.createByteArray(); + } + + @Override + public int describeContents() { + return 0; + } +} diff --git a/core/java/android/security/keystore/recovery/LockScreenRequiredException.java b/core/java/android/security/keystore/recovery/LockScreenRequiredException.java new file mode 100644 index 000000000000..ced23685690e --- /dev/null +++ b/core/java/android/security/keystore/recovery/LockScreenRequiredException.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.keystore.recovery; + +/** + * Error thrown when trying to generate keys for a profile that has no lock screen set. + * + * <p>A lock screen must be set, as the lock screen is used to encrypt the snapshot. + * + * @hide + */ +public class LockScreenRequiredException extends RecoveryControllerException { + public LockScreenRequiredException(String msg) { + super(msg); + } +} diff --git a/core/java/android/security/keystore/recovery/RecoveryClaim.java b/core/java/android/security/keystore/recovery/RecoveryClaim.java new file mode 100644 index 000000000000..11385d883a77 --- /dev/null +++ b/core/java/android/security/keystore/recovery/RecoveryClaim.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.keystore.recovery; + +/** + * An attempt to recover a keychain protected by remote secure hardware. + * + * @hide + */ +public class RecoveryClaim { + + private final RecoverySession mRecoverySession; + private final byte[] mClaimBytes; + + RecoveryClaim(RecoverySession recoverySession, byte[] claimBytes) { + mRecoverySession = recoverySession; + mClaimBytes = claimBytes; + } + + /** + * Returns the session associated with the recovery attempt. This is used to match the symmetric + * key, which remains internal to the framework, for decrypting the claim response. + * + * @return The session data. + */ + public RecoverySession getRecoverySession() { + return mRecoverySession; + } + + /** + * Returns the encrypted claim's bytes. + * + * <p>This should be sent by the recovery agent to the remote secure hardware, which will use + * it to decrypt the keychain, before sending it re-encrypted with the session's symmetric key + * to the device. + */ + public byte[] getClaimBytes() { + return mClaimBytes; + } +} diff --git a/core/java/android/security/keystore/recovery/RecoveryController.java b/core/java/android/security/keystore/recovery/RecoveryController.java new file mode 100644 index 000000000000..1908ce22bac2 --- /dev/null +++ b/core/java/android/security/keystore/recovery/RecoveryController.java @@ -0,0 +1,535 @@ +/* + * 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.security.keystore.recovery; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.PendingIntent; +import android.content.pm.PackageManager.NameNotFoundException; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.ServiceSpecificException; +import android.util.Log; + +import com.android.internal.widget.ILockSettings; + +import java.util.List; +import java.util.Map; + +/** + * An assistant for generating {@link javax.crypto.SecretKey} instances that can be recovered by + * other Android devices belonging to the user. The exported keychain is protected by the user's + * lock screen. + * + * <p>The RecoveryController must be paired with a recovery agent. The recovery agent is responsible + * for transporting the keychain to remote trusted hardware. This hardware must prevent brute force + * attempts against the user's lock screen by limiting the number of allowed guesses (to, e.g., 10). + * After that number of incorrect guesses, the trusted hardware no longer allows access to the + * key chain. + * + * <p>For now only the recovery agent itself is able to create keys, so it is expected that the + * recovery agent is itself the system app. + * + * <p>A recovery agent requires the privileged permission + * {@code android.Manifest.permission#RECOVER_KEYSTORE}. + * + * @hide + */ +public class RecoveryController { + private static final String TAG = "RecoveryController"; + + /** Key has been successfully synced. */ + public static final int RECOVERY_STATUS_SYNCED = 0; + /** Waiting for recovery agent to sync the key. */ + public static final int RECOVERY_STATUS_SYNC_IN_PROGRESS = 1; + /** Recovery account is not available. */ + public static final int RECOVERY_STATUS_MISSING_ACCOUNT = 2; + /** Key cannot be synced. */ + public static final int RECOVERY_STATUS_PERMANENT_FAILURE = 3; + + /** + * Failed because no snapshot is yet pending to be synced for the user. + * + * @hide + */ + public static final int ERROR_NO_SNAPSHOT_PENDING = 21; + + /** + * Failed due to an error internal to the recovery service. This is unexpected and indicates + * either a problem with the logic in the service, or a problem with a dependency of the + * service (such as AndroidKeyStore). + * + * @hide + */ + public static final int ERROR_SERVICE_INTERNAL_ERROR = 22; + + /** + * Failed because the user does not have a lock screen set. + * + * @hide + */ + public static final int ERROR_INSECURE_USER = 23; + + /** + * Error thrown when attempting to use a recovery session that has since been closed. + * + * @hide + */ + public static final int ERROR_SESSION_EXPIRED = 24; + + /** + * Failed because the provided certificate was not a valid X509 certificate. + * + * @hide + */ + public static final int ERROR_BAD_CERTIFICATE_FORMAT = 25; + + /** + * Error thrown if decryption failed. This might be because the tag is wrong, the key is wrong, + * the data has become corrupted, the data has been tampered with, etc. + * + * @hide + */ + public static final int ERROR_DECRYPTION_FAILED = 26; + + + private final ILockSettings mBinder; + + private RecoveryController(ILockSettings binder) { + mBinder = binder; + } + + /** + * Gets a new instance of the class. + */ + public static RecoveryController getInstance() { + ILockSettings lockSettings = + ILockSettings.Stub.asInterface(ServiceManager.getService("lock_settings")); + return new RecoveryController(lockSettings); + } + + /** + * Initializes key recovery service for the calling application. RecoveryController + * randomly chooses one of the keys from the list and keeps it to use for future key export + * operations. Collection of all keys in the list must be signed by the provided {@code + * rootCertificateAlias}, which must also be present in the list of root certificates + * preinstalled on the device. The random selection allows RecoveryController to select + * which of a set of remote recovery service devices will be used. + * + * <p>In addition, RecoveryController enforces a delay of three months between + * consecutive initialization attempts, to limit the ability of an attacker to often switch + * remote recovery devices and significantly increase number of recovery attempts. + * + * @param rootCertificateAlias alias of a root certificate preinstalled on the device + * @param signedPublicKeyList binary blob a list of X509 certificates and signature + * @throws BadCertificateFormatException if the {@code signedPublicKeyList} is in a bad format. + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. + */ + public void initRecoveryService( + @NonNull String rootCertificateAlias, @NonNull byte[] signedPublicKeyList) + throws BadCertificateFormatException, InternalRecoveryServiceException { + try { + mBinder.initRecoveryService(rootCertificateAlias, signedPublicKeyList); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (ServiceSpecificException e) { + if (e.errorCode == ERROR_BAD_CERTIFICATE_FORMAT) { + throw new BadCertificateFormatException(e.getMessage()); + } + throw wrapUnexpectedServiceSpecificException(e); + } + } + + /** + * Returns data necessary to store all recoverable keys for given account. Key material is + * encrypted with user secret and recovery public key. + * + * @param account specific to Recovery agent. + * @return Data necessary to recover keystore. + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. + */ + @NonNull public KeychainSnapshot getRecoveryData(@NonNull byte[] account) + throws InternalRecoveryServiceException { + try { + return mBinder.getRecoveryData(account); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (ServiceSpecificException e) { + if (e.errorCode == ERROR_NO_SNAPSHOT_PENDING) { + return null; + } + throw wrapUnexpectedServiceSpecificException(e); + } + } + + /** + * Sets a listener which notifies recovery agent that new recovery snapshot is available. {@link + * #getRecoveryData} can be used to get the snapshot. Note that every recovery agent can have at + * most one registered listener at any time. + * + * @param intent triggered when new snapshot is available. Unregisters listener if the value is + * {@code null}. + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. + */ + public void setSnapshotCreatedPendingIntent(@Nullable PendingIntent intent) + throws InternalRecoveryServiceException { + try { + mBinder.setSnapshotCreatedPendingIntent(intent); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (ServiceSpecificException e) { + throw wrapUnexpectedServiceSpecificException(e); + } + } + + /** + * Returns a map from recovery agent accounts to corresponding KeyStore recovery snapshot + * version. Version zero is used, if no snapshots were created for the account. + * + * @return Map from recovery agent accounts to snapshot versions. + * @see KeychainSnapshot#getSnapshotVersion + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. + */ + public @NonNull Map<byte[], Integer> getRecoverySnapshotVersions() + throws InternalRecoveryServiceException { + try { + // IPC doesn't support generic Maps. + @SuppressWarnings("unchecked") + Map<byte[], Integer> result = + (Map<byte[], Integer>) mBinder.getRecoverySnapshotVersions(); + return result; + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (ServiceSpecificException e) { + throw wrapUnexpectedServiceSpecificException(e); + } + } + + /** + * Server parameters used to generate new recovery key blobs. This value will be included in + * {@code KeychainSnapshot.getEncryptedRecoveryKeyBlob()}. The same value must be included + * in vaultParams {@link #startRecoverySession} + * + * @param serverParams included in recovery key blob. + * @see #getRecoveryData + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. + */ + public void setServerParams(byte[] serverParams) throws InternalRecoveryServiceException { + try { + mBinder.setServerParams(serverParams); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (ServiceSpecificException e) { + throw wrapUnexpectedServiceSpecificException(e); + } + } + + /** + * Updates recovery status for given keys. It is used to notify keystore that key was + * successfully stored on the server or there were an error. Application can check this value + * using {@code getRecoveyStatus}. + * + * @param packageName Application whose recoverable keys' statuses are to be updated. + * @param aliases List of application-specific key aliases. If the array is empty, updates the + * status for all existing recoverable keys. + * @param status Status specific to recovery agent. + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. + */ + public void setRecoveryStatus( + @NonNull String packageName, @Nullable String[] aliases, int status) + throws NameNotFoundException, InternalRecoveryServiceException { + try { + mBinder.setRecoveryStatus(packageName, aliases, status); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (ServiceSpecificException e) { + throw wrapUnexpectedServiceSpecificException(e); + } + } + + /** + * Returns a {@code Map} from Application's KeyStore key aliases to their recovery status. + * Negative status values are reserved for recovery agent specific codes. List of common codes: + * + * <ul> + * <li>{@link #RECOVERY_STATUS_SYNCED} + * <li>{@link #RECOVERY_STATUS_SYNC_IN_PROGRESS} + * <li>{@link #RECOVERY_STATUS_MISSING_ACCOUNT} + * <li>{@link #RECOVERY_STATUS_PERMANENT_FAILURE} + * </ul> + * + * @return {@code Map} from KeyStore alias to recovery status. + * @see #setRecoveryStatus + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. + */ + public Map<String, Integer> getRecoveryStatus() throws InternalRecoveryServiceException { + try { + // IPC doesn't support generic Maps. + @SuppressWarnings("unchecked") + Map<String, Integer> result = + (Map<String, Integer>) mBinder.getRecoveryStatus(/*packageName=*/ null); + return result; + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (ServiceSpecificException e) { + throw wrapUnexpectedServiceSpecificException(e); + } + } + + /** + * Specifies a set of secret types used for end-to-end keystore encryption. Knowing all of them + * is necessary to recover data. + * + * @param secretTypes {@link KeychainProtectionParams#TYPE_LOCKSCREEN} or {@link + * KeychainProtectionParams#TYPE_CUSTOM_PASSWORD} + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. + */ + public void setRecoverySecretTypes( + @NonNull @KeychainProtectionParams.UserSecretType int[] secretTypes) + throws InternalRecoveryServiceException { + try { + mBinder.setRecoverySecretTypes(secretTypes); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (ServiceSpecificException e) { + throw wrapUnexpectedServiceSpecificException(e); + } + } + + /** + * Defines a set of secret types used for end-to-end keystore encryption. Knowing all of them is + * necessary to generate KeychainSnapshot. + * + * @return list of recovery secret types + * @see KeychainSnapshot + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. + */ + public @NonNull @KeychainProtectionParams.UserSecretType int[] getRecoverySecretTypes() + throws InternalRecoveryServiceException { + try { + return mBinder.getRecoverySecretTypes(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (ServiceSpecificException e) { + throw wrapUnexpectedServiceSpecificException(e); + } + } + + /** + * Returns a list of recovery secret types, necessary to create a pending recovery snapshot. + * When user enters a secret of a pending type {@link #recoverySecretAvailable} should be + * called. + * + * @return list of recovery secret types + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. + */ + @NonNull + public @KeychainProtectionParams.UserSecretType int[] getPendingRecoverySecretTypes() + throws InternalRecoveryServiceException { + try { + return mBinder.getPendingRecoverySecretTypes(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (ServiceSpecificException e) { + throw wrapUnexpectedServiceSpecificException(e); + } + } + + /** + * Method notifies KeyStore that a user-generated secret is available. This method generates a + * symmetric session key which a trusted remote device can use to return a recovery key. Caller + * should use {@link KeychainProtectionParams#clearSecret} to override the secret value in + * memory. + * + * @param recoverySecret user generated secret together with parameters necessary to regenerate + * it on a new device. + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. + */ + public void recoverySecretAvailable(@NonNull KeychainProtectionParams recoverySecret) + throws InternalRecoveryServiceException { + try { + mBinder.recoverySecretAvailable(recoverySecret); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (ServiceSpecificException e) { + throw wrapUnexpectedServiceSpecificException(e); + } + } + + /** + * Initializes recovery session and returns a blob with proof of recovery secrets possession. + * The method generates symmetric key for a session, which trusted remote device can use to + * return recovery key. + * + * @param verifierPublicKey Encoded {@code java.security.cert.X509Certificate} with Public key + * used to create the recovery blob on the source device. + * Keystore will verify the certificate using root of trust. + * @param vaultParams Must match the parameters in the corresponding field in the recovery blob. + * Used to limit number of guesses. + * @param vaultChallenge Data passed from server for this recovery session and used to prevent + * replay attacks + * @param secrets Secrets provided by user, the method only uses type and secret fields. + * @return The recovery claim. Claim provides a b binary blob with recovery claim. It is + * encrypted with verifierPublicKey and contains a proof of user secrets, session symmetric + * key and parameters necessary to identify the counter with the number of failed recovery + * attempts. + * @throws BadCertificateFormatException if the {@code verifierPublicKey} is in an incorrect + * format. + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. + */ + @NonNull public RecoveryClaim startRecoverySession( + @NonNull byte[] verifierPublicKey, + @NonNull byte[] vaultParams, + @NonNull byte[] vaultChallenge, + @NonNull List<KeychainProtectionParams> secrets) + throws BadCertificateFormatException, InternalRecoveryServiceException { + try { + RecoverySession recoverySession = RecoverySession.newInstance(this); + byte[] recoveryClaim = + mBinder.startRecoverySession( + recoverySession.getSessionId(), + verifierPublicKey, + vaultParams, + vaultChallenge, + secrets); + return new RecoveryClaim(recoverySession, recoveryClaim); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (ServiceSpecificException e) { + if (e.errorCode == ERROR_BAD_CERTIFICATE_FORMAT) { + throw new BadCertificateFormatException(e.getMessage()); + } + throw wrapUnexpectedServiceSpecificException(e); + } + } + + /** + * Imports keys. + * + * @param session Related recovery session, as originally created by invoking + * {@link #startRecoverySession(byte[], byte[], byte[], List)}. + * @param recoveryKeyBlob Recovery blob encrypted by symmetric key generated for this session. + * @param applicationKeys Application keys. Key material can be decrypted using recoveryKeyBlob + * and session. KeyStore only uses package names from the application info in {@link + * WrappedApplicationKey}. Caller is responsibility to perform certificates check. + * @return Map from alias to raw key material. + * @throws SessionExpiredException if {@code session} has since been closed. + * @throws DecryptionFailedException if unable to decrypt the snapshot. + * @throws InternalRecoveryServiceException if an error occurs internal to the recovery service. + */ + public Map<String, byte[]> recoverKeys( + @NonNull RecoverySession session, + @NonNull byte[] recoveryKeyBlob, + @NonNull List<WrappedApplicationKey> applicationKeys) + throws SessionExpiredException, DecryptionFailedException, + InternalRecoveryServiceException { + try { + return (Map<String, byte[]>) mBinder.recoverKeys( + session.getSessionId(), recoveryKeyBlob, applicationKeys); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (ServiceSpecificException e) { + if (e.errorCode == ERROR_DECRYPTION_FAILED) { + throw new DecryptionFailedException(e.getMessage()); + } + if (e.errorCode == ERROR_SESSION_EXPIRED) { + throw new SessionExpiredException(e.getMessage()); + } + throw wrapUnexpectedServiceSpecificException(e); + } + } + + /** + * Deletes all data associated with {@code session}. Should not be invoked directly but via + * {@link RecoverySession#close()}. + * + * @hide + */ + void closeSession(RecoverySession session) { + try { + mBinder.closeSession(session.getSessionId()); + } catch (RemoteException | ServiceSpecificException e) { + Log.e(TAG, "Unexpected error trying to close session", e); + } + } + + /** + * Generates a key called {@code alias} and loads it into the recoverable key store. Returns the + * raw material of the key. + * + * @param alias The key alias. + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. + * @throws LockScreenRequiredException if the user has not set a lock screen. This is required + * to generate recoverable keys, as the snapshots are encrypted using a key derived from the + * lock screen. + */ + public byte[] generateAndStoreKey(@NonNull String alias) + throws InternalRecoveryServiceException, LockScreenRequiredException { + try { + return mBinder.generateAndStoreKey(alias); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (ServiceSpecificException e) { + if (e.errorCode == ERROR_INSECURE_USER) { + throw new LockScreenRequiredException(e.getMessage()); + } + throw wrapUnexpectedServiceSpecificException(e); + } + } + + /** + * Removes a key called {@code alias} from the recoverable key store. + * + * @param alias The key alias. + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. + */ + public void removeKey(@NonNull String alias) throws InternalRecoveryServiceException { + try { + mBinder.removeKey(alias); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (ServiceSpecificException e) { + throw wrapUnexpectedServiceSpecificException(e); + } + } + + private InternalRecoveryServiceException wrapUnexpectedServiceSpecificException( + ServiceSpecificException e) { + if (e.errorCode == ERROR_SERVICE_INTERNAL_ERROR) { + return new InternalRecoveryServiceException(e.getMessage()); + } + + // Should never happen. If it does, it's a bug, and we need to update how the method that + // called this throws its exceptions. + return new InternalRecoveryServiceException("Unexpected error code for method: " + + e.errorCode, e); + } +} diff --git a/core/java/android/security/keystore/recovery/RecoveryControllerException.java b/core/java/android/security/keystore/recovery/RecoveryControllerException.java new file mode 100644 index 000000000000..0fb7c07edd5b --- /dev/null +++ b/core/java/android/security/keystore/recovery/RecoveryControllerException.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.keystore.recovery; + +import java.security.GeneralSecurityException; + +/** + * Base exception for errors thrown by {@link RecoveryController}. + * + * @hide + */ +public abstract class RecoveryControllerException extends GeneralSecurityException { + RecoveryControllerException() { } + + RecoveryControllerException(String msg) { + super(msg); + } + + public RecoveryControllerException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/core/java/android/security/keystore/recovery/RecoverySession.java b/core/java/android/security/keystore/recovery/RecoverySession.java new file mode 100644 index 000000000000..89f894529739 --- /dev/null +++ b/core/java/android/security/keystore/recovery/RecoverySession.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.keystore.recovery; + +import java.security.SecureRandom; + +/** + * Session to recover a {@link KeychainSnapshot} from the remote trusted hardware, initiated by a + * recovery agent. + * + * @hide + */ +public class RecoverySession implements AutoCloseable { + + private static final int SESSION_ID_LENGTH_BYTES = 16; + + private final String mSessionId; + private final RecoveryController mRecoveryController; + + private RecoverySession(RecoveryController recoveryController, String sessionId) { + mRecoveryController = recoveryController; + mSessionId = sessionId; + } + + /** + * A new session, started by {@code recoveryManager}. + */ + static RecoverySession newInstance(RecoveryController recoveryController) { + return new RecoverySession(recoveryController, newSessionId()); + } + + /** + * Returns a new random session ID. + */ + private static String newSessionId() { + SecureRandom secureRandom = new SecureRandom(); + byte[] sessionId = new byte[SESSION_ID_LENGTH_BYTES]; + secureRandom.nextBytes(sessionId); + StringBuilder sb = new StringBuilder(); + for (byte b : sessionId) { + sb.append(Byte.toHexString(b, /*upperCase=*/ false)); + } + return sb.toString(); + } + + /** + * An internal session ID, used by the framework to match recovery claims to snapshot responses. + */ + String getSessionId() { + return mSessionId; + } + + @Override + public void close() { + mRecoveryController.closeSession(this); + } +} diff --git a/core/java/android/security/keystore/recovery/SessionExpiredException.java b/core/java/android/security/keystore/recovery/SessionExpiredException.java new file mode 100644 index 000000000000..7fc2b0560d69 --- /dev/null +++ b/core/java/android/security/keystore/recovery/SessionExpiredException.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.keystore.recovery; + +/** + * Error thrown when attempting to use a {@link RecoverySession} that has since expired. + * + * @hide + */ +public class SessionExpiredException extends RecoveryControllerException { + public SessionExpiredException(String msg) { + super(msg); + } +} diff --git a/core/java/android/security/keystore/WrappedApplicationKey.aidl b/core/java/android/security/keystore/recovery/WrappedApplicationKey.aidl index a6294fee03b3..b2d1ae461346 100644 --- a/core/java/android/security/keystore/WrappedApplicationKey.aidl +++ b/core/java/android/security/keystore/recovery/WrappedApplicationKey.aidl @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.security.keystore; +package android.security.keystore.recovery; /* @hide */ parcelable WrappedApplicationKey; diff --git a/core/java/android/security/keystore/recovery/WrappedApplicationKey.java b/core/java/android/security/keystore/recovery/WrappedApplicationKey.java new file mode 100644 index 000000000000..bca03b389e43 --- /dev/null +++ b/core/java/android/security/keystore/recovery/WrappedApplicationKey.java @@ -0,0 +1,145 @@ +/* + * 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.security.keystore.recovery; + +import android.annotation.NonNull; +import android.os.Parcel; +import android.os.Parcelable; + +import com.android.internal.util.Preconditions; + +/** + * Helper class with data necessary recover a single application key, given a recovery key. + * + * <ul> + * <li>Alias - Keystore alias of the key. + * <li>Encrypted key material. + * </ul> + * + * Note that Application info is not included. Recovery Agent can only make its own keys + * recoverable. + * + * @hide + */ +public final class WrappedApplicationKey implements Parcelable { + private String mAlias; + // The only supported format is AES-256 symmetric key. + private byte[] mEncryptedKeyMaterial; + + /** + * Builder for creating {@link WrappedApplicationKey}. + */ + public static class Builder { + private WrappedApplicationKey + mInstance = new WrappedApplicationKey(); + + /** + * Sets Application-specific alias of the key. + * + * @param alias The alias. + * @return This builder. + */ + public Builder setAlias(@NonNull String alias) { + mInstance.mAlias = alias; + return this; + } + + /** + * Sets key material encrypted by recovery key. + * + * @param encryptedKeyMaterial The key material + * @return This builder + */ + + public Builder setEncryptedKeyMaterial(@NonNull byte[] encryptedKeyMaterial) { + mInstance.mEncryptedKeyMaterial = encryptedKeyMaterial; + return this; + } + + /** + * Creates a new {@link WrappedApplicationKey} instance. + * + * @return new instance + * @throws NullPointerException if some required fields were not set. + */ + @NonNull public WrappedApplicationKey build() { + Preconditions.checkNotNull(mInstance.mAlias); + Preconditions.checkNotNull(mInstance.mEncryptedKeyMaterial); + return mInstance; + } + } + + private WrappedApplicationKey() { + + } + + /** + * Deprecated - consider using Builder. + * @hide + */ + public WrappedApplicationKey(@NonNull String alias, @NonNull byte[] encryptedKeyMaterial) { + mAlias = Preconditions.checkNotNull(alias); + mEncryptedKeyMaterial = Preconditions.checkNotNull(encryptedKeyMaterial); + } + + /** + * Application-specific alias of the key. + * + * @see java.security.KeyStore.aliases + */ + public @NonNull String getAlias() { + return mAlias; + } + + /** Key material encrypted by recovery key. */ + public @NonNull byte[] getEncryptedKeyMaterial() { + return mEncryptedKeyMaterial; + } + + public static final Creator<WrappedApplicationKey> CREATOR = + new Creator<WrappedApplicationKey>() { + public WrappedApplicationKey createFromParcel(Parcel in) { + return new WrappedApplicationKey(in); + } + + public WrappedApplicationKey[] newArray(int length) { + return new WrappedApplicationKey[length]; + } + }; + + /** + * @hide + */ + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeString(mAlias); + out.writeByteArray(mEncryptedKeyMaterial); + } + + /** + * @hide + */ + protected WrappedApplicationKey(Parcel in) { + mAlias = in.readString(); + mEncryptedKeyMaterial = in.createByteArray(); + } + + @Override + public int describeContents() { + return 0; + } +} diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java index f5c36139df0f..990fbdb019d6 100644 --- a/core/java/android/view/animation/AnimationUtils.java +++ b/core/java/android/view/animation/AnimationUtils.java @@ -156,6 +156,8 @@ public class AnimationUtils { anim = new RotateAnimation(c, attrs); } else if (name.equals("translate")) { anim = new TranslateAnimation(c, attrs); + } else if (name.equals("cliprect")) { + anim = new ClipRectAnimation(c, attrs); } else { throw new RuntimeException("Unknown animation name: " + parser.getName()); } diff --git a/core/java/android/view/animation/ClipRectAnimation.java b/core/java/android/view/animation/ClipRectAnimation.java index e194927e8301..21509d3a1159 100644 --- a/core/java/android/view/animation/ClipRectAnimation.java +++ b/core/java/android/view/animation/ClipRectAnimation.java @@ -16,7 +16,11 @@ package android.view.animation; +import android.content.Context; +import android.content.res.TypedArray; import android.graphics.Rect; +import android.util.AttributeSet; +import android.util.DisplayMetrics; /** * An animation that controls the clip of an object. See the @@ -26,8 +30,84 @@ import android.graphics.Rect; * @hide */ public class ClipRectAnimation extends Animation { - protected Rect mFromRect = new Rect(); - protected Rect mToRect = new Rect(); + protected final Rect mFromRect = new Rect(); + protected final Rect mToRect = new Rect(); + + private int mFromLeftType = ABSOLUTE; + private int mFromTopType = ABSOLUTE; + private int mFromRightType = ABSOLUTE; + private int mFromBottomType = ABSOLUTE; + + private int mToLeftType = ABSOLUTE; + private int mToTopType = ABSOLUTE; + private int mToRightType = ABSOLUTE; + private int mToBottomType = ABSOLUTE; + + private float mFromLeftValue; + private float mFromTopValue; + private float mFromRightValue; + private float mFromBottomValue; + + private float mToLeftValue; + private float mToTopValue; + private float mToRightValue; + private float mToBottomValue; + + /** + * Constructor used when a ClipRectAnimation is loaded from a resource. + * + * @param context Application context to use + * @param attrs Attribute set from which to read values + */ + public ClipRectAnimation(Context context, AttributeSet attrs) { + super(context, attrs); + + TypedArray a = context.obtainStyledAttributes(attrs, + com.android.internal.R.styleable.ClipRectAnimation); + + Description d = Description.parseValue(a.peekValue( + com.android.internal.R.styleable.ClipRectAnimation_fromLeft)); + mFromLeftType = d.type; + mFromLeftValue = d.value; + + d = Description.parseValue(a.peekValue( + com.android.internal.R.styleable.ClipRectAnimation_fromTop)); + mFromTopType = d.type; + mFromTopValue = d.value; + + d = Description.parseValue(a.peekValue( + com.android.internal.R.styleable.ClipRectAnimation_fromRight)); + mFromRightType = d.type; + mFromRightValue = d.value; + + d = Description.parseValue(a.peekValue( + com.android.internal.R.styleable.ClipRectAnimation_fromBottom)); + mFromBottomType = d.type; + mFromBottomValue = d.value; + + + d = Description.parseValue(a.peekValue( + com.android.internal.R.styleable.ClipRectAnimation_toLeft)); + mToLeftType = d.type; + mToLeftValue = d.value; + + d = Description.parseValue(a.peekValue( + com.android.internal.R.styleable.ClipRectAnimation_toTop)); + mToTopType = d.type; + mToTopValue = d.value; + + d = Description.parseValue(a.peekValue( + com.android.internal.R.styleable.ClipRectAnimation_toRight)); + mToRightType = d.type; + mToRightValue = d.value; + + d = Description.parseValue(a.peekValue( + com.android.internal.R.styleable.ClipRectAnimation_toBottom)); + mToBottomType = d.type; + mToBottomValue = d.value; + + a.recycle(); + } /** * Constructor to use when building a ClipRectAnimation from code @@ -39,8 +119,15 @@ public class ClipRectAnimation extends Animation { if (fromClip == null || toClip == null) { throw new RuntimeException("Expected non-null animation clip rects"); } - mFromRect.set(fromClip); - mToRect.set(toClip); + mFromLeftValue = fromClip.left; + mFromTopValue = fromClip.top; + mFromRightValue= fromClip.right; + mFromBottomValue = fromClip.bottom; + + mToLeftValue = toClip.left; + mToTopValue = toClip.top; + mToRightValue= toClip.right; + mToBottomValue = toClip.bottom; } /** @@ -48,8 +135,7 @@ public class ClipRectAnimation extends Animation { */ public ClipRectAnimation(int fromL, int fromT, int fromR, int fromB, int toL, int toT, int toR, int toB) { - mFromRect.set(fromL, fromT, fromR, fromB); - mToRect.set(toL, toT, toR, toB); + this(new Rect(fromL, fromT, fromR, fromB), new Rect(toL, toT, toR, toB)); } @Override @@ -65,4 +151,17 @@ public class ClipRectAnimation extends Animation { public boolean willChangeTransformationMatrix() { return false; } + + @Override + public void initialize(int width, int height, int parentWidth, int parentHeight) { + super.initialize(width, height, parentWidth, parentHeight); + mFromRect.set((int) resolveSize(mFromLeftType, mFromLeftValue, width, parentWidth), + (int) resolveSize(mFromTopType, mFromTopValue, height, parentHeight), + (int) resolveSize(mFromRightType, mFromRightValue, width, parentWidth), + (int) resolveSize(mFromBottomType, mFromBottomValue, height, parentHeight)); + mToRect.set((int) resolveSize(mToLeftType, mToLeftValue, width, parentWidth), + (int) resolveSize(mToTopType, mToTopValue, height, parentHeight), + (int) resolveSize(mToRightType, mToRightValue, width, parentWidth), + (int) resolveSize(mToBottomType, mToBottomValue, height, parentHeight)); + } } diff --git a/core/java/com/android/internal/net/INetworkWatchlistManager.aidl b/core/java/com/android/internal/net/INetworkWatchlistManager.aidl index ee01a23af686..d69c7deab375 100644 --- a/core/java/com/android/internal/net/INetworkWatchlistManager.aidl +++ b/core/java/com/android/internal/net/INetworkWatchlistManager.aidl @@ -24,4 +24,5 @@ interface INetworkWatchlistManager { boolean stopWatchlistLogging(); void reloadWatchlist(); void reportWatchlistIfNecessary(); + byte[] getWatchlistConfigHash(); } diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index b1c45f729fcb..039b66d4cd7d 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -6947,6 +6947,8 @@ public class BatteryStatsImpl extends BatteryStats { WIFI_MULTICAST_ENABLED, mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase); } mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs); + StatsLog.write_non_chained( + StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED, getUid(), null, 1); } } @@ -6955,6 +6957,8 @@ public class BatteryStatsImpl extends BatteryStats { if (mWifiMulticastEnabled) { mWifiMulticastEnabled = false; mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs); + StatsLog.write_non_chained( + StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED, getUid(), null, 0); } } diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl index e3f1f472ce5e..f9da1eb26669 100644 --- a/core/java/com/android/internal/widget/ILockSettings.aidl +++ b/core/java/com/android/internal/widget/ILockSettings.aidl @@ -19,9 +19,9 @@ package com.android.internal.widget; import android.app.PendingIntent; import android.app.trust.IStrongAuthTracker; import android.os.Bundle; -import android.security.keystore.WrappedApplicationKey; -import android.security.keystore.KeychainSnapshot; -import android.security.keystore.KeychainProtectionParams; +import android.security.keystore.recovery.WrappedApplicationKey; +import android.security.keystore.recovery.KeychainSnapshot; +import android.security.keystore.recovery.KeychainProtectionParams; import com.android.internal.widget.ICheckCredentialProgressCallback; import com.android.internal.widget.VerifyCredentialResponse; diff --git a/core/jni/android/graphics/AnimatedImageDrawable.cpp b/core/jni/android/graphics/AnimatedImageDrawable.cpp index 12feaab5c684..ec15cce1f1d5 100644 --- a/core/jni/android/graphics/AnimatedImageDrawable.cpp +++ b/core/jni/android/graphics/AnimatedImageDrawable.cpp @@ -58,8 +58,7 @@ static jlong AnimatedImageDrawable_nCreate(JNIEnv* env, jobject /*clazz*/, SkPictureRecorder recorder; SkCanvas* skcanvas = recorder.beginRecording(bounds); std::unique_ptr<Canvas> canvas(Canvas::create_canvas(skcanvas)); - postProcessAndRelease(env, jpostProcess, std::move(canvas), bounds.width(), - bounds.height()); + postProcessAndRelease(env, jpostProcess, std::move(canvas)); if (env->ExceptionCheck()) { return 0; } diff --git a/core/jni/android/graphics/ByteBufferStreamAdaptor.cpp b/core/jni/android/graphics/ByteBufferStreamAdaptor.cpp index 115edd4fe4f4..85c9ef36b82e 100644 --- a/core/jni/android/graphics/ByteBufferStreamAdaptor.cpp +++ b/core/jni/android/graphics/ByteBufferStreamAdaptor.cpp @@ -67,7 +67,7 @@ public: } if (!buffer) { - return this->setPosition(mPosition + size); + return this->setPosition(mPosition + size) ? size : 0; } auto* env = get_env_or_die(mJvm); diff --git a/core/jni/android/graphics/ImageDecoder.cpp b/core/jni/android/graphics/ImageDecoder.cpp index 1c2528ffecd4..743a7efa2b24 100644 --- a/core/jni/android/graphics/ImageDecoder.cpp +++ b/core/jni/android/graphics/ImageDecoder.cpp @@ -37,15 +37,13 @@ using namespace android; static jclass gImageDecoder_class; -static jclass gPoint_class; +static jclass gSize_class; static jclass gIncomplete_class; -static jclass gCorrupt_class; static jclass gCanvas_class; static jmethodID gImageDecoder_constructorMethodID; static jmethodID gImageDecoder_postProcessMethodID; -static jmethodID gPoint_constructorMethodID; +static jmethodID gSize_constructorMethodID; static jmethodID gIncomplete_constructorMethodID; -static jmethodID gCorrupt_constructorMethodID; static jmethodID gCallback_onPartialImageMethodID; static jmethodID gCanvas_constructorMethodID; static jmethodID gCanvas_releaseMethodID; @@ -157,8 +155,7 @@ static jobject ImageDecoder_nCreateByteArray(JNIEnv* env, jobject /*clazz*/, jby return native_create(env, std::move(stream)); } -jint postProcessAndRelease(JNIEnv* env, jobject jimageDecoder, std::unique_ptr<Canvas> canvas, - int width, int height) { +jint postProcessAndRelease(JNIEnv* env, jobject jimageDecoder, std::unique_ptr<Canvas> canvas) { jobject jcanvas = env->NewObject(gCanvas_class, gCanvas_constructorMethodID, reinterpret_cast<jlong>(canvas.get())); if (!jcanvas) { @@ -169,8 +166,7 @@ jint postProcessAndRelease(JNIEnv* env, jobject jimageDecoder, std::unique_ptr<C // jcanvas now owns canvas. canvas.release(); - return env->CallIntMethod(jimageDecoder, gImageDecoder_postProcessMethodID, - jcanvas, width, height); + return env->CallIntMethod(jimageDecoder, gImageDecoder_postProcessMethodID, jcanvas); } // Note: jpostProcess points to an ImageDecoder object if it has a PostProcess object, and nullptr @@ -271,39 +267,47 @@ static jobject ImageDecoder_nDecodeBitmap(JNIEnv* env, jobject /*clazz*/, jlong if (jexception) { env->ExceptionClear(); } + int onPartialImageError = jexception ? 1 // ImageDecoder.java's ERROR_SOURCE_EXCEPTION + : 0; // No error. switch (result) { case SkCodec::kSuccess: // Ignore the exception, since the decode was successful anyway. jexception = nullptr; + onPartialImageError = 0; break; case SkCodec::kIncompleteInput: - if (jcallback && !jexception) { - jexception = (jthrowable) env->NewObject(gIncomplete_class, - gIncomplete_constructorMethodID); + if (!jexception) { + onPartialImageError = 2; // ImageDecoder.java's ERROR_SOURCE_EXCEPTION } break; case SkCodec::kErrorInInput: - if (jcallback && !jexception) { - jexception = (jthrowable) env->NewObject(gCorrupt_class, - gCorrupt_constructorMethodID); + if (!jexception) { + onPartialImageError = 3; // ImageDecoder.java's ERROR_SOURCE_ERROR } break; default: SkString msg; - msg.printf("getPixels failed with error %i", result); + msg.printf("getPixels failed with error %s", SkCodec::ResultToString(result)); doThrowIOE(env, msg.c_str()); return nullptr; } - if (jexception) { - bool throwException = !env->CallBooleanMethod(jcallback, gCallback_onPartialImageMethodID, - jexception); + if (jexception || onPartialImageError) { + bool throwException = !jcallback || + !env->CallBooleanMethod(jcallback, gCallback_onPartialImageMethodID, + onPartialImageError); if (env->ExceptionCheck()) { return nullptr; } if (throwException) { - env->Throw(jexception); + if (jexception) { + env->Throw(jexception); + } else if (onPartialImageError == 2) { + env->ThrowNew(gIncomplete_class, "Incomplete input"); + } else { + doThrowIOE(env, "image has an error!"); + } return nullptr; } } @@ -399,8 +403,7 @@ static jobject ImageDecoder_nDecodeBitmap(JNIEnv* env, jobject /*clazz*/, jlong if (jpostProcess) { std::unique_ptr<Canvas> canvas(Canvas::create_canvas(bm)); - jint pixelFormat = postProcessAndRelease(env, jpostProcess, std::move(canvas), - bm.width(), bm.height()); + jint pixelFormat = postProcessAndRelease(env, jpostProcess, std::move(canvas)); if (env->ExceptionCheck()) { return nullptr; } @@ -472,7 +475,7 @@ static jobject ImageDecoder_nGetSampledSize(JNIEnv* env, jobject /*clazz*/, jlon jint sampleSize) { auto* decoder = reinterpret_cast<ImageDecoder*>(nativePtr); SkISize size = decoder->mCodec->getSampledDimensions(sampleSize); - return env->NewObject(gPoint_class, gPoint_constructorMethodID, size.width(), size.height()); + return env->NewObject(gSize_class, gSize_constructorMethodID, size.width(), size.height()); } static void ImageDecoder_nGetPadding(JNIEnv* env, jobject /*clazz*/, jlong nativePtr, @@ -496,9 +499,9 @@ static const JNINativeMethod gImageDecoderMethods[] = { { "nCreate", "([BII)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateByteArray }, { "nCreate", "(Ljava/io/InputStream;[B)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateInputStream }, { "nCreate", "(Ljava/io/FileDescriptor;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateFd }, - { "nDecodeBitmap", "(JLandroid/graphics/ImageDecoder$OnPartialImageListener;Landroid/graphics/ImageDecoder;IILandroid/graphics/Rect;ZIZZZ)Landroid/graphics/Bitmap;", + { "nDecodeBitmap", "(JLandroid/graphics/ImageDecoder;Landroid/graphics/ImageDecoder;IILandroid/graphics/Rect;ZIZZZ)Landroid/graphics/Bitmap;", (void*) ImageDecoder_nDecodeBitmap }, - { "nGetSampledSize","(JI)Landroid/graphics/Point;", (void*) ImageDecoder_nGetSampledSize }, + { "nGetSampledSize","(JI)Landroid/util/Size;", (void*) ImageDecoder_nGetSampledSize }, { "nGetPadding", "(JLandroid/graphics/Rect;)V", (void*) ImageDecoder_nGetPadding }, { "nClose", "(J)V", (void*) ImageDecoder_nClose}, { "nGetMimeType", "(J)Ljava/lang/String;", (void*) ImageDecoder_nGetMimeType }, @@ -507,19 +510,15 @@ static const JNINativeMethod gImageDecoderMethods[] = { int register_android_graphics_ImageDecoder(JNIEnv* env) { gImageDecoder_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/ImageDecoder")); gImageDecoder_constructorMethodID = GetMethodIDOrDie(env, gImageDecoder_class, "<init>", "(JIIZ)V"); - gImageDecoder_postProcessMethodID = GetMethodIDOrDie(env, gImageDecoder_class, "postProcessAndRelease", "(Landroid/graphics/Canvas;II)I"); + gImageDecoder_postProcessMethodID = GetMethodIDOrDie(env, gImageDecoder_class, "postProcessAndRelease", "(Landroid/graphics/Canvas;)I"); - gPoint_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Point")); - gPoint_constructorMethodID = GetMethodIDOrDie(env, gPoint_class, "<init>", "(II)V"); + gSize_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/util/Size")); + gSize_constructorMethodID = GetMethodIDOrDie(env, gSize_class, "<init>", "(II)V"); gIncomplete_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/ImageDecoder$IncompleteException")); gIncomplete_constructorMethodID = GetMethodIDOrDie(env, gIncomplete_class, "<init>", "()V"); - gCorrupt_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/ImageDecoder$CorruptException")); - gCorrupt_constructorMethodID = GetMethodIDOrDie(env, gCorrupt_class, "<init>", "()V"); - - jclass callback_class = FindClassOrDie(env, "android/graphics/ImageDecoder$OnPartialImageListener"); - gCallback_onPartialImageMethodID = GetMethodIDOrDie(env, callback_class, "onPartialImage", "(Ljava/io/IOException;)Z"); + gCallback_onPartialImageMethodID = GetMethodIDOrDie(env, gImageDecoder_class, "onPartialImage", "(I)Z"); gCanvas_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Canvas")); gCanvas_constructorMethodID = GetMethodIDOrDie(env, gCanvas_class, "<init>", "(J)V"); diff --git a/core/jni/android/graphics/ImageDecoder.h b/core/jni/android/graphics/ImageDecoder.h index 2df71eb19528..5d7e67690c22 100644 --- a/core/jni/android/graphics/ImageDecoder.h +++ b/core/jni/android/graphics/ImageDecoder.h @@ -51,5 +51,4 @@ struct ImageDecoder { // Creates a Java Canvas object from canvas, calls jimageDecoder's PostProcess on it, and then // releases the Canvas. // Caller needs to check for exceptions. -jint postProcessAndRelease(JNIEnv* env, jobject jimageDecoder, std::unique_ptr<Canvas> canvas, - int width, int height); +jint postProcessAndRelease(JNIEnv* env, jobject jimageDecoder, std::unique_ptr<Canvas> canvas); diff --git a/core/jni/android_database_SQLiteCommon.cpp b/core/jni/android_database_SQLiteCommon.cpp index 34544d37a6bf..daa20876ba65 100644 --- a/core/jni/android_database_SQLiteCommon.cpp +++ b/core/jni/android_database_SQLiteCommon.cpp @@ -223,8 +223,8 @@ void throw_sqlite3_exception(JNIEnv* env, int errcode, if (sqlite3Message) { String8 fullMessage; fullMessage.append(sqlite3Message); - const char* errcode_msg = sqlite3_error_code_to_msg(errcode).c_str(); - fullMessage.appendFormat(" (code %s)", errcode_msg); // print extended error code + std::string errcode_msg = sqlite3_error_code_to_msg(errcode); + fullMessage.appendFormat(" (code %s)", errcode_msg.c_str()); // print extended error code if (message) { fullMessage.append(": "); fullMessage.append(message); diff --git a/core/res/res/anim/activity_close_enter.xml b/core/res/res/anim/activity_close_enter.xml index a67b0ca38519..371bcfef7ec9 100644 --- a/core/res/res/anim/activity_close_enter.xml +++ b/core/res/res/anim/activity_close_enter.xml @@ -17,9 +17,17 @@ */ --> -<set xmlns:android="http://schemas.android.com/apk/res/android" android:zAdjustment="normal"> - <alpha android:fromAlpha="0.7" android:toAlpha="1.0" - android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/linear_out_slow_in" - android:duration="250"/> +<set xmlns:android="http://schemas.android.com/apk/res/android" + android:shareInterpolator="false"> + <translate + android:fromYDelta="-2%" + android:toYDelta="0" + android:interpolator="@interpolator/fast_out_slow_in" + android:duration="425"/> + <alpha + android:fromAlpha="0.9" + android:toAlpha="1.0" + android:interpolator="@interpolator/activity_close_dim" + android:startOffset="0" + android:duration="425"/> </set>
\ No newline at end of file diff --git a/core/res/res/anim/activity_close_exit.xml b/core/res/res/anim/activity_close_exit.xml index d8c42ed808f1..143bedb985e1 100644 --- a/core/res/res/anim/activity_close_exit.xml +++ b/core/res/res/anim/activity_close_exit.xml @@ -18,15 +18,27 @@ --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:shareInterpolator="false" android:zAdjustment="top"> - <alpha android:fromAlpha="1.0" android:toAlpha="0.0" - android:interpolator="@interpolator/linear" - android:fillEnabled="true" - android:fillBefore="false" android:fillAfter="true" - android:startOffset="100" - android:duration="150"/> - <translate android:fromYDelta="0%" android:toYDelta="8%" - android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/accelerate_quart" - android:duration="250"/> + android:shareInterpolator="false" + android:zAdjustment="top"> + <translate + android:fromYDelta="0" + android:toYDelta="4.1%" + android:interpolator="@interpolator/fast_out_slow_in" + android:duration="425"/> + <cliprect + android:fromLeft="0%" + android:fromTop="0%" + android:fromRight="100%" + android:fromBottom="100%" + android:toLeft="0%" + android:toTop="95.9%" + android:toRight="100%" + android:toBottom="100%" + android:interpolator="@interpolator/exaggerated_ease" + android:duration="425"/> + <alpha + android:fromAlpha="1.0" + android:toAlpha="1.0" + android:interpolator="@interpolator/fast_out_linear_in" + android:duration="425"/> </set>
\ No newline at end of file diff --git a/core/res/res/anim/activity_open_enter.xml b/core/res/res/anim/activity_open_enter.xml index 1d949d2f7446..f9381b458c20 100644 --- a/core/res/res/anim/activity_open_enter.xml +++ b/core/res/res/anim/activity_open_enter.xml @@ -1,5 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- +<?xml version="1.0" encoding="utf-8"?><!-- /* ** Copyright 2009, The Android Open Source Project ** @@ -18,15 +17,21 @@ --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:shareInterpolator="false" - android:zAdjustment="top"> - <alpha android:fromAlpha="0.0" android:toAlpha="1.0" - android:interpolator="@interpolator/decelerate_quart" - android:fillEnabled="true" - android:fillBefore="false" android:fillAfter="true" - android:duration="200"/> - <translate android:fromYDelta="8%" android:toYDelta="0" - android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/decelerate_quint" - android:duration="350"/> + android:shareInterpolator="false"> + <translate + android:fromYDelta="4.1%" + android:toYDelta="0" + android:interpolator="@interpolator/fast_out_slow_in" + android:duration="425"/> + <cliprect + android:fromLeft="0%" + android:fromTop="95.9%" + android:fromRight="100%" + android:fromBottom="100%" + android:toLeft="0%" + android:toTop="0%" + android:toRight="100%" + android:toBottom="100%" + android:interpolator="@interpolator/exaggerated_ease" + android:duration="425"/> </set>
\ No newline at end of file diff --git a/core/res/res/anim/activity_open_exit.xml b/core/res/res/anim/activity_open_exit.xml index 3a84197f8f63..d52b150391fb 100644 --- a/core/res/res/anim/activity_open_exit.xml +++ b/core/res/res/anim/activity_open_exit.xml @@ -1,5 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- +<?xml version="1.0" encoding="utf-8"?><!-- /* ** Copyright 2009, The Android Open Source Project ** @@ -18,9 +17,15 @@ --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:background="#ff000000" android:zAdjustment="normal"> - <alpha android:fromAlpha="1.0" android:toAlpha="0.7" - android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true" - android:interpolator="@interpolator/fast_out_slow_in" - android:duration="217"/> + android:shareInterpolator="false"> + <translate + android:fromYDelta="0" + android:toYDelta="-2%" + android:interpolator="@interpolator/fast_out_slow_in" + android:duration="425"/> + <alpha + android:fromAlpha="1.0" + android:toAlpha="0.9" + android:interpolator="@interpolator/linear" + android:duration="117"/> </set>
\ No newline at end of file diff --git a/core/res/res/anim/task_close_enter.xml b/core/res/res/anim/task_close_enter.xml index bea0ee51d593..81d1300038e3 100644 --- a/core/res/res/anim/task_close_enter.xml +++ b/core/res/res/anim/task_close_enter.xml @@ -1,5 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- +<?xml version="1.0" encoding="utf-8"?><!-- /* ** Copyright 2009, The Android Open Source Project ** @@ -16,27 +15,54 @@ ** limitations under the License. */ --> - <set xmlns:android="http://schemas.android.com/apk/res/android" - android:shareInterpolator="false" android:zAdjustment="normal"> + android:shareInterpolator="false" + android:zAdjustment="top"> + + <alpha + android:fromAlpha="1" + android:toAlpha="1.0" + android:fillEnabled="true" + android:fillBefore="true" + android:fillAfter="true" + android:interpolator="@interpolator/linear" + android:startOffset="67" + android:duration="217"/> - <alpha android:fromAlpha="0.6" android:toAlpha="1.0" - android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/decelerate_cubic" - android:startOffset="600" - android:duration="133"/> + <translate + android:fromXDelta="105%" + android:toXDelta="0" + android:fillEnabled="true" + android:fillBefore="true" + android:fillAfter="true" + android:interpolator="@interpolator/aggressive_ease" + android:startOffset="50" + android:duration="383"/> - <translate android:fromYDelta="10%" android:toYDelta="0" - android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/decelerate_cubic" - android:startOffset="300" - android:duration="433" /> + <scale + android:fromXScale="1.0526" + android:toXScale="1" + android:fromYScale="1.0526" + android:toYScale="1" + android:pivotX="50%" + android:pivotY="50%" + android:fillEnabled="true" + android:fillBefore="true" + android:fillAfter="true" + android:interpolator="@interpolator/fast_out_slow_in" + android:duration="283"/> - <scale android:fromXScale=".9" android:toXScale="1.0" - android:fromYScale=".9" android:toYScale="1.0" - android:pivotX="50%p" android:pivotY="0%p" - android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/fast_out_slow_in" - android:startOffset="300" - android:duration="433" /> + <scale + android:fromXScale="0.95" + android:toXScale="1" + android:fromYScale="0.95" + android:toYScale="1" + android:pivotX="50%" + android:pivotY="50%" + android:fillEnabled="true" + android:fillBefore="true" + android:fillAfter="true" + android:interpolator="@interpolator/fast_out_slow_in" + android:startOffset="283" + android:duration="317"/> </set>
\ No newline at end of file diff --git a/core/res/res/anim/task_close_exit.xml b/core/res/res/anim/task_close_exit.xml index b6a08070c3ce..ab8b89ce7b06 100644 --- a/core/res/res/anim/task_close_exit.xml +++ b/core/res/res/anim/task_close_exit.xml @@ -1,5 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- +<?xml version="1.0" encoding="utf-8"?><!-- /* ** Copyright 2009, The Android Open Source Project ** @@ -18,20 +17,44 @@ --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:shareInterpolator="false" android:zAdjustment="top"> + android:shareInterpolator="false"> - <alpha android:fromAlpha="1.0" android:toAlpha="0" - android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/accelerate_quad" - android:startOffset="250" - android:duration="167"/> + <alpha + android:fromAlpha="1.0" + android:toAlpha="1" + android:fillEnabled="true" + android:fillBefore="true" + android:fillAfter="true" + android:interpolator="@interpolator/linear" + android:startOffset="67" + android:duration="283"/> - <translate android:fromYDelta="0" android:toYDelta="110%" - android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/accelerate_quint" - android:duration="417"/> + <translate + android:fromXDelta="0" + android:toXDelta="-105%" + android:fillEnabled="true" + android:fillBefore="true" + android:fillAfter="true" + android:interpolator="@interpolator/aggressive_ease" + android:startOffset="50" + android:duration="383"/> + + <scale + android:fromXScale="1.0" + android:toXScale="0.95" + android:fromYScale="1.0" + android:toYScale="0.95" + android:fillEnabled="true" + android:fillBefore="true" + android:fillAfter="true" + android:pivotX="50%" + android:pivotY="50%" + android:interpolator="@interpolator/fast_out_slow_in" + android:duration="283"/> <!-- This is needed to keep the animation running while task_open_enter completes --> - <alpha android:fromAlpha="1.0" android:toAlpha="1.0" - android:duration="700" /> + <alpha + android:fromAlpha="1.0" + android:toAlpha="1.0" + android:duration="600"/> </set>
\ No newline at end of file diff --git a/core/res/res/anim/task_open_enter.xml b/core/res/res/anim/task_open_enter.xml index b73e14fc637f..2ee7cd86e323 100644 --- a/core/res/res/anim/task_open_enter.xml +++ b/core/res/res/anim/task_open_enter.xml @@ -1,5 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- +<?xml version="1.0" encoding="utf-8"?><!-- /* ** Copyright 2009, The Android Open Source Project ** @@ -15,20 +14,55 @@ ** See the License for the specific language governing permissions and ** limitations under the License. */ ---> -<!-- This should in sync with task_open_enter_cross_profile_apps.xml --> +--><!-- This should in sync with task_open_enter_cross_profile_apps.xml --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:shareInterpolator="false" android:zAdjustment="top"> + android:shareInterpolator="false" + android:zAdjustment="top"> - <alpha android:fromAlpha="0" android:toAlpha="1.0" - android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/decelerate_quart" - android:startOffset="300" - android:duration="167"/> + <alpha + android:fromAlpha="1" + android:toAlpha="1.0" + android:fillEnabled="true" + android:fillBefore="true" + android:fillAfter="true" + android:interpolator="@interpolator/linear" + android:startOffset="67" + android:duration="217"/> - <translate android:fromYDelta="110%" android:toYDelta="0" - android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/decelerate_quint" - android:startOffset="300" - android:duration="417" /> + <translate + android:fromXDelta="-105%" + android:toXDelta="0" + android:fillEnabled="true" + android:fillBefore="true" + android:fillAfter="true" + android:interpolator="@interpolator/aggressive_ease" + android:startOffset="50" + android:duration="383"/> + + <scale + android:fromXScale="1.0526" + android:toXScale="1" + android:fromYScale="1.0526" + android:toYScale="1" + android:pivotX="50%" + android:pivotY="50%" + android:fillEnabled="true" + android:fillBefore="true" + android:fillAfter="true" + android:interpolator="@interpolator/fast_out_slow_in" + android:duration="283"/> + + <scale + android:fromXScale="0.95" + android:toXScale="1" + android:fromYScale="0.95" + android:toYScale="1" + android:pivotX="50%" + android:pivotY="50%" + android:fillEnabled="true" + android:fillBefore="true" + android:fillAfter="true" + android:interpolator="@interpolator/fast_out_slow_in" + android:startOffset="283" + android:duration="317"/> </set>
\ No newline at end of file diff --git a/core/res/res/anim/task_open_enter_cross_profile_apps.xml b/core/res/res/anim/task_open_enter_cross_profile_apps.xml index ad89fde92065..a92425e89960 100644 --- a/core/res/res/anim/task_open_enter_cross_profile_apps.xml +++ b/core/res/res/anim/task_open_enter_cross_profile_apps.xml @@ -18,24 +18,61 @@ --> <!-- This should in sync with task_open_enter.xml --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:shareInterpolator="false" android:zAdjustment="top"> + android:shareInterpolator="false" + android:zAdjustment="top"> - <alpha android:fromAlpha="0" android:toAlpha="1.0" - android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/decelerate_quart" - android:startOffset="300" - android:duration="167"/> + <alpha + android:fromAlpha="1" + android:toAlpha="1.0" + android:fillEnabled="true" + android:fillBefore="true" + android:fillAfter="true" + android:interpolator="@interpolator/linear" + android:startOffset="67" + android:duration="217"/> - <translate android:fromYDelta="110%" android:toYDelta="0" - android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/decelerate_quint" - android:startOffset="300" - android:duration="417"/> + <translate + android:fromXDelta="-105%" + android:toXDelta="0" + android:fillEnabled="true" + android:fillBefore="true" + android:fillAfter="true" + android:interpolator="@interpolator/aggressive_ease" + android:startOffset="50" + android:duration="383"/> + + <scale + android:fromXScale="1.0526" + android:toXScale="1" + android:fromYScale="1.0526" + android:toYScale="1" + android:pivotX="50%" + android:pivotY="50%" + android:fillEnabled="true" + android:fillBefore="true" + android:fillAfter="true" + android:interpolator="@interpolator/fast_out_slow_in" + android:duration="283"/> + + <scale + android:fromXScale="0.95" + android:toXScale="1" + android:fromYScale="0.95" + android:toYScale="1" + android:pivotX="50%" + android:pivotY="50%" + android:fillEnabled="true" + android:fillBefore="true" + android:fillAfter="true" + android:interpolator="@interpolator/fast_out_slow_in" + android:startOffset="283" + android:duration="317"/> <!-- To keep the transition around longer for the thumbnail, should be kept in sync with cross_profile_apps_thumbmail.xml --> - <alpha android:fromAlpha="1.0" android:toAlpha="1.0" - android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:startOffset="717" - android:duration="200"/> + <alpha + android:fromAlpha="1.0" + android:toAlpha="1.0" + android:startOffset="717" + android:duration="200"/> </set>
\ No newline at end of file diff --git a/core/res/res/anim/task_open_exit.xml b/core/res/res/anim/task_open_exit.xml index 78d0fb015ce3..ecb98ce2cb16 100644 --- a/core/res/res/anim/task_open_exit.xml +++ b/core/res/res/anim/task_open_exit.xml @@ -1,5 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- +<?xml version="1.0" encoding="utf-8"?><!-- /* ** Copyright 2009, The Android Open Source Project ** @@ -18,26 +17,44 @@ --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:background="#ff000000" android:shareInterpolator="false" android:zAdjustment="normal"> + android:shareInterpolator="false"> - <alpha android:fromAlpha="1.0" android:toAlpha="0.6" - android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/accelerate_cubic" - android:duration="133"/> + <alpha + android:fromAlpha="1.0" + android:toAlpha="1" + android:fillEnabled="true" + android:fillBefore="true" + android:fillAfter="true" + android:interpolator="@interpolator/linear" + android:startOffset="67" + android:duration="283"/> - <translate android:fromYDelta="0" android:toYDelta="10%" - android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/accelerate_cubic" - android:duration="433"/> + <translate + android:fromXDelta="0" + android:toXDelta="105%" + android:fillEnabled="true" + android:fillBefore="true" + android:fillAfter="true" + android:interpolator="@interpolator/aggressive_ease" + android:startOffset="50" + android:duration="383"/> - <scale android:fromXScale="1.0" android:toXScale="0.9" - android:fromYScale="1.0" android:toYScale="0.9" - android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:pivotX="50%p" android:pivotY="50%p" - android:interpolator="@interpolator/fast_out_slow_in" - android:duration="433" /> + <scale + android:fromXScale="1.0" + android:toXScale="0.95" + android:fromYScale="1.0" + android:toYScale="0.95" + android:fillEnabled="true" + android:fillBefore="true" + android:fillAfter="true" + android:pivotX="50%" + android:pivotY="50%" + android:interpolator="@interpolator/fast_out_slow_in" + android:duration="283"/> <!-- This is needed to keep the animation running while task_open_enter completes --> - <alpha android:fromAlpha="1.0" android:toAlpha="1.0" - android:duration="700" /> + <alpha + android:fromAlpha="1.0" + android:toAlpha="1.0" + android:duration="600"/> </set>
\ No newline at end of file diff --git a/core/res/res/interpolator/activity_close_dim.xml b/core/res/res/interpolator/activity_close_dim.xml new file mode 100644 index 000000000000..faad1399ff49 --- /dev/null +++ b/core/res/res/interpolator/activity_close_dim.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2018 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> + +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:controlX1="0.33" + android:controlY1="0" + android:controlX2="1" + android:controlY2="1"/> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 4eaf93d822b2..ffe68dc4195b 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -6336,6 +6336,17 @@ <attr name="toAlpha" format="float" /> </declare-styleable> + <declare-styleable name="ClipRectAnimation"> + <attr name="fromLeft" format="fraction" /> + <attr name="fromTop" format="fraction" /> + <attr name="fromRight" format="fraction" /> + <attr name="fromBottom" format="fraction" /> + <attr name="toLeft" format="fraction" /> + <attr name="toTop" format="fraction" /> + <attr name="toRight" format="fraction" /> + <attr name="toBottom" format="fraction" /> + </declare-styleable> + <declare-styleable name="LayoutAnimation"> <!-- Fraction of the animation duration used to delay the beginning of the animation of each child. --> diff --git a/core/res/res/values/locale_config.xml b/core/res/res/values/locale_config.xml index 2c4058acc972..35eee6a3b175 100644 --- a/core/res/res/values/locale_config.xml +++ b/core/res/res/values/locale_config.xml @@ -23,35 +23,60 @@ <item>ak-GH</item> <!-- Akan (Ghana) --> <item>am-ET</item> <!-- Amharic (Ethiopia) --> <item>ar-AE</item> <!-- Arabic (United Arab Emirates) --> + <item>ar-AE-u-nu-latn</item> <!-- Arabic (United Arab Emirates,Western Digits) --> <item>ar-BH</item> <!-- Arabic (Bahrain) --> + <item>ar-BH-u-nu-latn</item> <!-- Arabic (Bahrain,Western Digits) --> <item>ar-DJ</item> <!-- Arabic (Djibouti) --> + <item>ar-DJ-u-nu-latn</item> <!-- Arabic (Djibouti,Western Digits) --> <item>ar-DZ</item> <!-- Arabic (Algeria) --> + <item>ar-DZ-u-nu-arab</item> <!-- Arabic (Algeria,Arabic-Indic Digits) --> <item>ar-EG</item> <!-- Arabic (Egypt) --> <item>ar-EG-u-nu-latn</item> <!-- Arabic (Egypt,Western Digits) --> <item>ar-EH</item> <!-- Arabic (Western Sahara) --> + <item>ar-EH-u-nu-arab</item> <!-- Arabic (Western Sahara,Arabic-Indic Digits) --> <item>ar-ER</item> <!-- Arabic (Eritrea) --> + <item>ar-ER-u-nu-latn</item> <!-- Arabic (Eritrea,Western Digits) --> <item>ar-IL</item> <!-- Arabic (Israel) --> + <item>ar-IL-u-nu-latn</item> <!-- Arabic (Israel,Western Digits) --> <item>ar-IQ</item> <!-- Arabic (Iraq) --> + <item>ar-IQ-u-nu-latn</item> <!-- Arabic (Iraq,Western Digits) --> <item>ar-JO</item> <!-- Arabic (Jordan) --> + <item>ar-JO-u-nu-latn</item> <!-- Arabic (Jordan,Western Digits) --> <item>ar-KM</item> <!-- Arabic (Comoros) --> + <item>ar-KM-u-nu-latn</item> <!-- Arabic (Comoros,Western Digits) --> <item>ar-KW</item> <!-- Arabic (Kuwait) --> + <item>ar-KW-u-nu-latn</item> <!-- Arabic (Kuwait,Western Digits) --> <item>ar-LB</item> <!-- Arabic (Lebanon) --> + <item>ar-LB-u-nu-latn</item> <!-- Arabic (Lebanon,Western Digits) --> <item>ar-LY</item> <!-- Arabic (Libya) --> + <item>ar-LY-u-nu-arab</item> <!-- Arabic (Libya,Arabic-Indic Digits) --> <item>ar-MA</item> <!-- Arabic (Morocco) --> + <item>ar-MA-u-nu-arab</item> <!-- Arabic (Morocco,Arabic-Indic Digits) --> <item>ar-MR</item> <!-- Arabic (Mauritania) --> + <item>ar-MR-u-nu-latn</item> <!-- Arabic (Mauritania,Western Digits) --> <item>ar-OM</item> <!-- Arabic (Oman) --> + <item>ar-OM-u-nu-latn</item> <!-- Arabic (Oman,Western Digits) --> <item>ar-PS</item> <!-- Arabic (Palestine) --> + <item>ar-PS-u-nu-latn</item> <!-- Arabic (Palestine,Western Digits) --> <item>ar-QA</item> <!-- Arabic (Qatar) --> + <item>ar-QA-u-nu-latn</item> <!-- Arabic (Qatar,Western Digits) --> <item>ar-SA</item> <!-- Arabic (Saudi Arabia) --> + <item>ar-SA-u-nu-latn</item> <!-- Arabic (Saudi Arabia,Western Digits) --> <item>ar-SD</item> <!-- Arabic (Sudan) --> + <item>ar-SD-u-nu-latn</item> <!-- Arabic (Sudan,Western Digits) --> <item>ar-SO</item> <!-- Arabic (Somalia) --> + <item>ar-SO-u-nu-latn</item> <!-- Arabic (Somalia,Western Digits) --> <item>ar-SS</item> <!-- Arabic (South Sudan) --> + <item>ar-SS-u-nu-latn</item> <!-- Arabic (South Sudan,Western Digits) --> <item>ar-SY</item> <!-- Arabic (Syria) --> + <item>ar-SY-u-nu-latn</item> <!-- Arabic (Syria,Western Digits) --> <item>ar-TD</item> <!-- Arabic (Chad) --> + <item>ar-TD-u-nu-latn</item> <!-- Arabic (Chad,Western Digits) --> <item>ar-TN</item> <!-- Arabic (Tunisia) --> <item>ar-TN-u-nu-arab</item> <!-- Arabic (Tunisia,Arabic-Indic Digits) --> <item>ar-XB</item> <!-- Right-to-left pseudolocale --> <item>ar-YE</item> <!-- Arabic (Yemen) --> + <item>ar-YE-u-nu-latn</item> <!-- Arabic (Yemen,Western Digits) --> <item>as-IN</item> <!-- Assamese (India) --> <item>asa-TZ</item> <!-- Asu (Tanzania) --> <item>az-Cyrl-AZ</item> <!-- Azerbaijani (Cyrillic,Azerbaijan) --> @@ -63,7 +88,9 @@ <item>bg-BG</item> <!-- Bulgarian (Bulgaria) --> <item>bm-ML</item> <!-- Bambara (Mali) --> <item>bn-BD</item> <!-- Bengali (Bangladesh) --> + <item>bn-BD-u-nu-latn</item> <!-- Bengali (Bangladesh,Western Digits) --> <item>bn-IN</item> <!-- Bengali (India) --> + <item>bn-IN-u-nu-latn</item> <!-- Bengali (India,Western Digits) --> <item>bo-CN</item> <!-- Tibetan (China) --> <item>bo-IN</item> <!-- Tibetan (India) --> <item>br-FR</item> <!-- Breton (France) --> @@ -230,7 +257,9 @@ <item>eu-ES</item> <!-- Basque (Spain) --> <item>ewo-CM</item> <!-- Ewondo (Cameroon) --> <item>fa-AF</item> <!-- Persian (Afghanistan) --> + <item>fa-AF-u-nu-latn</item> <!-- Persian (Afghanistan,Western Digits) --> <item>fa-IR</item> <!-- Persian (Iran) --> + <item>fa-IR-u-nu-latn</item> <!-- Persian (Iran,Western Digits) --> <item>ff-CM</item> <!-- Fulah (Cameroon) --> <item>ff-GN</item> <!-- Fulah (Guinea) --> <item>ff-MR</item> <!-- Fulah (Mauritania) --> @@ -473,7 +502,9 @@ <item>ug-CN</item> <!-- Uyghur (China) --> <item>uk-UA</item> <!-- Ukrainian (Ukraine) --> <item>ur-IN</item> <!-- Urdu (India) --> + <item>ur-IN-u-nu-latn</item> <!-- Urdu (India,Western Digits) --> <item>ur-PK</item> <!-- Urdu (Pakistan) --> + <item>ur-PK-u-nu-arabext</item> <!-- Urdu (Pakistan,Extended Arabic-Indic Digits) --> <item>uz-Arab-AF</item> <!-- Uzbek (Arabic,Afghanistan) --> <item>uz-Cyrl-UZ</item> <!-- Uzbek (Cyrillic,Uzbekistan) --> <item>uz-Latn-UZ</item> <!-- Uzbek (Latin,Uzbekistan) --> diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java index 4d715d1cb9ea..02d22bec5828 100644 --- a/graphics/java/android/graphics/ImageDecoder.java +++ b/graphics/java/android/graphics/ImageDecoder.java @@ -16,6 +16,7 @@ package android.graphics; +import static android.system.OsConstants.SEEK_CUR; import static android.system.OsConstants.SEEK_SET; import android.annotation.IntDef; @@ -31,6 +32,7 @@ import android.graphics.drawable.Drawable; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.NinePatchDrawable; import android.net.Uri; +import android.util.Size; import android.system.ErrnoException; import android.system.Os; import android.util.DisplayMetrics; @@ -40,6 +42,7 @@ import libcore.io.IoUtils; import dalvik.system.CloseGuard; import java.nio.ByteBuffer; +import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -55,14 +58,16 @@ import java.util.concurrent.atomic.AtomicBoolean; /** * Class for decoding images as {@link Bitmap}s or {@link Drawable}s. - * @hide */ public final class ImageDecoder implements AutoCloseable { /** * Source of the encoded image data. */ public static abstract class Source { + private Source() {} + /* @hide */ + @Nullable Resources getResources() { return null; } /* @hide */ @@ -79,11 +84,12 @@ public final class ImageDecoder implements AutoCloseable { } /* @hide */ + @NonNull abstract ImageDecoder createImageDecoder() throws IOException; }; private static class ByteArraySource extends Source { - ByteArraySource(byte[] data, int offset, int length) { + ByteArraySource(@NonNull byte[] data, int offset, int length) { mData = data; mOffset = offset; mLength = length; @@ -99,7 +105,7 @@ public final class ImageDecoder implements AutoCloseable { } private static class ByteBufferSource extends Source { - ByteBufferSource(ByteBuffer buffer) { + ByteBufferSource(@NonNull ByteBuffer buffer) { mBuffer = buffer; } private final ByteBuffer mBuffer; @@ -116,7 +122,7 @@ public final class ImageDecoder implements AutoCloseable { } private static class ContentResolverSource extends Source { - ContentResolverSource(ContentResolver resolver, Uri uri) { + ContentResolverSource(@NonNull ContentResolver resolver, @NonNull Uri uri) { mResolver = resolver; mUri = uri; } @@ -167,7 +173,31 @@ public final class ImageDecoder implements AutoCloseable { } } - private static ImageDecoder createFromStream(InputStream is) throws IOException { + @NonNull + private static ImageDecoder createFromFile(@NonNull File file) throws IOException { + FileInputStream stream = new FileInputStream(file); + FileDescriptor fd = stream.getFD(); + try { + Os.lseek(fd, 0, SEEK_CUR); + } catch (ErrnoException e) { + return createFromStream(stream); + } + + ImageDecoder decoder = null; + try { + decoder = nCreate(fd); + } finally { + if (decoder == null) { + IoUtils.closeQuietly(stream); + } else { + decoder.mInputStream = stream; + } + } + return decoder; + } + + @NonNull + private static ImageDecoder createFromStream(@NonNull InputStream is) throws IOException { // Arbitrary size matches BitmapFactory. byte[] storage = new byte[16 * 1024]; ImageDecoder decoder = null; @@ -220,7 +250,7 @@ public final class ImageDecoder implements AutoCloseable { } private static class ResourceSource extends Source { - ResourceSource(Resources res, int resId) { + ResourceSource(@NonNull Resources res, int resId) { mResources = res; mResId = resId; mResDensity = Bitmap.DENSITY_NONE; @@ -269,59 +299,54 @@ public final class ImageDecoder implements AutoCloseable { } } + private static class FileSource extends Source { + FileSource(@NonNull File file) { + mFile = file; + } + + private final File mFile; + + @Override + public ImageDecoder createImageDecoder() throws IOException { + return createFromFile(mFile); + } + } + /** * Contains information about the encoded image. */ public static class ImageInfo { - /** - * Width of the image, without scaling or cropping. - */ - public final int width; + private final Size mSize; + private ImageDecoder mDecoder; + + private ImageInfo(@NonNull ImageDecoder decoder) { + mSize = new Size(decoder.mWidth, decoder.mHeight); + mDecoder = decoder; + } /** - * Height of the image, without scaling or cropping. + * Size of the image, without scaling or cropping. */ - public final int height; - - /* @hide */ - ImageDecoder decoder; - - /* @hide */ - ImageInfo(ImageDecoder decoder) { - this.width = decoder.mWidth; - this.height = decoder.mHeight; - this.decoder = decoder; + @NonNull + public Size getSize() { + return mSize; } /** - * The mimeType of the image, if known. + * The mimeType of the image. */ + @NonNull public String getMimeType() { - return decoder.getMimeType(); + return mDecoder.getMimeType(); } }; /** - * Used if the provided data is incomplete. - * - * May be thrown if there is nothing to display. - * - * If supplied to onPartialImage, there may be a correct partial image to - * display. + * Thrown if the provided data is incomplete. */ public static class IncompleteException extends IOException {}; /** - * Used if the provided data is corrupt. - * - * May be thrown if there is nothing to display. - * - * If supplied to onPartialImage, there may be a correct partial image to - * display. - */ - public static class CorruptException extends IOException {}; - - /** * Optional listener supplied to {@link #decodeDrawable} or * {@link #decodeBitmap}. */ @@ -329,31 +354,55 @@ public final class ImageDecoder implements AutoCloseable { /** * Called when the header is decoded and the size is known. * - * @param info Information about the encoded image. * @param decoder allows changing the default settings of the decode. + * @param info Information about the encoded image. + * @param source that created the decoder. */ - public void onHeaderDecoded(ImageInfo info, ImageDecoder decoder); + public void onHeaderDecoded(@NonNull ImageDecoder decoder, + @NonNull ImageInfo info, @NonNull Source source); }; /** + * An Exception was thrown reading the {@link Source}. + */ + public static final int ERROR_SOURCE_EXCEPTION = 1; + + /** + * The encoded data was incomplete. + */ + public static final int ERROR_SOURCE_INCOMPLETE = 2; + + /** + * The encoded data contained an error. + */ + public static final int ERROR_SOURCE_ERROR = 3; + + @Retention(SOURCE) + @IntDef({ ERROR_SOURCE_EXCEPTION, ERROR_SOURCE_INCOMPLETE, ERROR_SOURCE_ERROR }) + public @interface Error {}; + + /** * Optional listener supplied to the ImageDecoder. + * + * Without this listener, errors will throw {@link java.io.IOException}. */ public static interface OnPartialImageListener { /** * Called when there is only a partial image to display. * - * If the input is incomplete or contains an error, this listener lets - * the client know that and allows them to optionally bypass the rest - * of the decode/creation process. + * If decoding is interrupted after having decoded a partial image, + * this listener lets the client know that and allows them to + * optionally finish the rest of the decode/creation process to create + * a partial {@link Drawable}/{@link Bitmap}. * - * @param e IOException containing information about the error that - * interrupted the decode. - * @return True (which is the default) to create and return a - * {@link Drawable}/{@link Bitmap} with partial data. False to - * abort the decode and throw the {@link java.io.IOException}. + * @param error indicating what interrupted the decode. + * @param source that had the error. + * @return True to create and return a {@link Drawable}/{@link Bitmap} + * with partial data. False (which is the default) to abort the + * decode and throw {@link java.io.IOException}. */ - public boolean onPartialImage(IOException e); + public boolean onPartialImage(@Error int error, @NonNull Source source); }; // Fields @@ -364,14 +413,15 @@ public final class ImageDecoder implements AutoCloseable { private int mDesiredWidth; private int mDesiredHeight; - private int mAllocator = DEFAULT_ALLOCATOR; + private int mAllocator = ALLOCATOR_DEFAULT; private boolean mRequireUnpremultiplied = false; private boolean mMutable = false; private boolean mPreferRamOverQuality = false; private boolean mAsAlphaMask = false; private Rect mCropRect; + private Source mSource; - private PostProcess mPostProcess; + private PostProcessor mPostProcessor; private OnPartialImageListener mOnPartialImageListener; // Objects for interacting with the input. @@ -412,6 +462,7 @@ public final class ImageDecoder implements AutoCloseable { /** * Create a new {@link Source} from an asset. + * @hide * * @param res the {@link Resources} object containing the image data. * @param resId resource ID of the image data. @@ -441,6 +492,7 @@ public final class ImageDecoder implements AutoCloseable { /** * Create a new {@link Source} from a byte array. + * * @param data byte array of compressed image data. * @param offset offset into data for where the decoder should begin * parsing. @@ -448,7 +500,9 @@ public final class ImageDecoder implements AutoCloseable { * @throws NullPointerException if data is null. * @throws ArrayIndexOutOfBoundsException if offset and length are * not within data. + * @hide */ + @NonNull public static Source createSource(@NonNull byte[] data, int offset, int length) throws ArrayIndexOutOfBoundsException { if (data == null) { @@ -464,7 +518,9 @@ public final class ImageDecoder implements AutoCloseable { /** * See {@link #createSource(byte[], int, int). + * @hide */ + @NonNull public static Source createSource(@NonNull byte[] data) { return createSource(data, 0, data.length); } @@ -472,13 +528,15 @@ public final class ImageDecoder implements AutoCloseable { /** * Create a new {@link Source} from a {@link java.nio.ByteBuffer}. * - * The returned {@link Source} effectively takes ownership of the + * <p>The returned {@link Source} effectively takes ownership of the * {@link java.nio.ByteBuffer}; i.e. no other code should modify it after - * this call. + * this call.</p> * - * Decoding will start from {@link java.nio.ByteBuffer#position()}. + * Decoding will start from {@link java.nio.ByteBuffer#position()}. The + * position after decoding is undefined. */ - public static Source createSource(ByteBuffer buffer) { + @NonNull + public static Source createSource(@NonNull ByteBuffer buffer) { return new ByteBufferSource(buffer); } @@ -499,20 +557,29 @@ public final class ImageDecoder implements AutoCloseable { } /** + * Create a new {@link Source} from a {@link java.io.File}. + */ + @NonNull + public static Source createSource(@NonNull File file) { + return new FileSource(file); + } + + /** * Return the width and height of a given sample size. * - * This takes an input that functions like + * <p>This takes an input that functions like * {@link BitmapFactory.Options#inSampleSize}. It returns a width and * height that can be acheived by sampling the encoded image. Other widths * and heights may be supported, but will require an additional (internal) * scaling step. Such internal scaling is *not* supported with - * {@link #requireUnpremultiplied}. + * {@link #setRequireUnpremultiplied} set to {@code true}.</p> * * @param sampleSize Sampling rate of the encoded image. - * @return Point {@link Point#x} and {@link Point#y} correspond to the - * width and height after sampling. + * @return {@link android.util.Size} of the width and height after + * sampling. */ - public Point getSampledSize(int sampleSize) { + @NonNull + public Size getSampledSize(int sampleSize) { if (sampleSize <= 0) { throw new IllegalArgumentException("sampleSize must be positive! " + "provided " + sampleSize); @@ -531,7 +598,7 @@ public final class ImageDecoder implements AutoCloseable { * @param width must be greater than 0. * @param height must be greater than 0. */ - public void resize(int width, int height) { + public void setResize(int width, int height) { if (width <= 0 || height <= 0) { throw new IllegalArgumentException("Dimensions must be positive! " + "provided (" + width + ", " + height + ")"); @@ -544,14 +611,14 @@ public final class ImageDecoder implements AutoCloseable { /** * Resize based on a sample size. * - * This has the same effect as passing the result of - * {@link #getSampledSize} to {@link #resize(int, int)}. + * <p>This has the same effect as passing the result of + * {@link #getSampledSize} to {@link #setResize(int, int)}.</p> * * @param sampleSize Sampling rate of the encoded image. */ - public void resize(int sampleSize) { - Point dimensions = this.getSampledSize(sampleSize); - this.resize(dimensions.x, dimensions.y); + public void setResize(int sampleSize) { + Size size = this.getSampledSize(sampleSize); + this.setResize(size.getWidth(), size.getHeight()); } private boolean requestedResize() { @@ -567,7 +634,7 @@ public final class ImageDecoder implements AutoCloseable { * switch to software when HARDWARE is incompatible, e.g. * {@link #setMutable}, {@link #setAsAlphaMask}. */ - public static final int DEFAULT_ALLOCATOR = 0; + public static final int ALLOCATOR_DEFAULT = 0; /** * Use a software allocation for the pixel memory. @@ -575,28 +642,29 @@ public final class ImageDecoder implements AutoCloseable { * Useful for drawing to a software {@link Canvas} or for * accessing the pixels on the final output. */ - public static final int SOFTWARE_ALLOCATOR = 1; + public static final int ALLOCATOR_SOFTWARE = 1; /** * Use shared memory for the pixel memory. * * Useful for sharing across processes. */ - public static final int SHARED_MEMORY_ALLOCATOR = 2; + public static final int ALLOCATOR_SHARED_MEMORY = 2; /** * Require a {@link Bitmap.Config#HARDWARE} {@link Bitmap}. * - * This will throw an {@link java.lang.IllegalStateException} when combined - * with incompatible options, like {@link #setMutable} or - * {@link #setAsAlphaMask}. + * When this is combined with incompatible options, like + * {@link #setMutable} or {@link #setAsAlphaMask}, {@link #decodeDrawable} + * / {@link #decodeBitmap} will throw an + * {@link java.lang.IllegalStateException}. */ - public static final int HARDWARE_ALLOCATOR = 3; + public static final int ALLOCATOR_HARDWARE = 3; /** @hide **/ @Retention(SOURCE) - @IntDef({ DEFAULT_ALLOCATOR, SOFTWARE_ALLOCATOR, SHARED_MEMORY_ALLOCATOR, - HARDWARE_ALLOCATOR }) + @IntDef({ ALLOCATOR_DEFAULT, ALLOCATOR_SOFTWARE, ALLOCATOR_SHARED_MEMORY, + ALLOCATOR_HARDWARE }) public @interface Allocator {}; /** @@ -604,47 +672,46 @@ public final class ImageDecoder implements AutoCloseable { * * This is ignored for animated drawables. * - * TODO: Allow accessing the backing from the Bitmap. - * * @param allocator Type of allocator to use. */ public void setAllocator(@Allocator int allocator) { - if (allocator < DEFAULT_ALLOCATOR || allocator > HARDWARE_ALLOCATOR) { + if (allocator < ALLOCATOR_DEFAULT || allocator > ALLOCATOR_HARDWARE) { throw new IllegalArgumentException("invalid allocator " + allocator); } mAllocator = allocator; } /** - * Create a {@link Bitmap} with unpremultiplied pixels. + * Specify whether the {@link Bitmap} should have unpremultiplied pixels. * * By default, ImageDecoder will create a {@link Bitmap} with * premultiplied pixels, which is required for drawing with the * {@link android.view.View} system (i.e. to a {@link Canvas}). Calling - * this method will result in {@link #decodeBitmap} returning a - * {@link Bitmap} with unpremultiplied pixels. See - * {@link Bitmap#isPremultiplied}. Incompatible with + * this method with a value of {@code true} will result in + * {@link #decodeBitmap} returning a {@link Bitmap} with unpremultiplied + * pixels. See {@link Bitmap#isPremultiplied}. This is incompatible with * {@link #decodeDrawable}; attempting to decode an unpremultiplied * {@link Drawable} will throw an {@link java.lang.IllegalStateException}. */ - public void requireUnpremultiplied() { - mRequireUnpremultiplied = true; + public void setRequireUnpremultiplied(boolean requireUnpremultiplied) { + mRequireUnpremultiplied = requireUnpremultiplied; } /** * Modify the image after decoding and scaling. * - * This allows adding effects prior to returning a {@link Drawable} or + * <p>This allows adding effects prior to returning a {@link Drawable} or * {@link Bitmap}. For a {@code Drawable} or an immutable {@code Bitmap}, - * this is the only way to process the image after decoding. + * this is the only way to process the image after decoding.</p> * - * If set on a nine-patch image, the nine-patch data is ignored. + * <p>If set on a nine-patch image, the nine-patch data is ignored.</p> * - * For an animated image, the drawing commands drawn on the {@link Canvas} - * will be recorded immediately and then applied to each frame. + * <p>For an animated image, the drawing commands drawn on the + * {@link Canvas} will be recorded immediately and then applied to each + * frame.</p> */ - public void setPostProcess(PostProcess p) { - mPostProcess = p; + public void setPostProcessor(@Nullable PostProcessor p) { + mPostProcessor = p; } /** @@ -653,66 +720,72 @@ public final class ImageDecoder implements AutoCloseable { * Will be called if there is an error in the input. Without one, a * partial {@link Bitmap} will be created. */ - public void setOnPartialImageListener(OnPartialImageListener l) { + public void setOnPartialImageListener(@Nullable OnPartialImageListener l) { mOnPartialImageListener = l; } /** * Crop the output to {@code subset} of the (possibly) scaled image. * - * {@code subset} must be contained within the size set by {@link #resize} - * or the bounds of the image if resize was not called. Otherwise an - * {@link IllegalStateException} will be thrown. + * <p>{@code subset} must be contained within the size set by + * {@link #setResize} or the bounds of the image if setResize was not + * called. Otherwise an {@link IllegalStateException} will be thrown by + * {@link #decodeDrawable}/{@link #decodeBitmap}.</p> * - * NOT intended as a replacement for + * <p>NOT intended as a replacement for * {@link BitmapRegionDecoder#decodeRegion}. This supports all formats, - * but merely crops the output. + * but merely crops the output.</p> */ - public void crop(Rect subset) { + public void setCrop(@Nullable Rect subset) { mCropRect = subset; } /** - * Create a mutable {@link Bitmap}. + * Specify whether the {@link Bitmap} should be mutable. * - * By default, a {@link Bitmap} created will be immutable, but that can be - * changed with this call. + * <p>By default, a {@link Bitmap} created will be immutable, but that can + * be changed with this call.</p> * - * Incompatible with {@link #HARDWARE_ALLOCATOR}, because - * {@link Bitmap.Config#HARDWARE} Bitmaps cannot be mutable. Attempting to - * combine them will throw an {@link java.lang.IllegalStateException}. + * <p>Mutable Bitmaps are incompatible with {@link #ALLOCATOR_HARDWARE}, + * because {@link Bitmap.Config#HARDWARE} Bitmaps cannot be mutable. + * Attempting to combine them will throw an + * {@link java.lang.IllegalStateException}.</p> * - * Incompatible with {@link #decodeDrawable}, which would require - * retrieving the Bitmap from the returned Drawable in order to modify. - * Attempting to decode a mutable {@link Drawable} will throw an - * {@link java.lang.IllegalStateException} + * <p>Mutable Bitmaps are also incompatible with {@link #decodeDrawable}, + * which would require retrieving the Bitmap from the returned Drawable in + * order to modify. Attempting to decode a mutable {@link Drawable} will + * throw an {@link java.lang.IllegalStateException}.</p> */ - public void setMutable() { - mMutable = true; + public void setMutable(boolean mutable) { + mMutable = mutable; } /** - * Potentially save RAM at the expense of quality. + * Specify whether to potentially save RAM at the expense of quality. * - * This may result in a {@link Bitmap} with a denser {@link Bitmap.Config}, - * depending on the image. For example, for an opaque {@link Bitmap}, this - * may result in a {@link Bitmap.Config} with no alpha information. + * Setting this to {@code true} may result in a {@link Bitmap} with a + * denser {@link Bitmap.Config}, depending on the image. For example, for + * an opaque {@link Bitmap}, this may result in a {@link Bitmap.Config} + * with no alpha information. */ - public void setPreferRamOverQuality() { - mPreferRamOverQuality = true; + public void setPreferRamOverQuality(boolean preferRamOverQuality) { + mPreferRamOverQuality = preferRamOverQuality; } /** - * Potentially treat the output as an alpha mask. + * Specify whether to potentially treat the output as an alpha mask. * - * If the image is encoded in a format with only one channel, treat that - * channel as alpha. Otherwise this call has no effect. + * <p>If this is set to {@code true} and the image is encoded in a format + * with only one channel, treat that channel as alpha. Otherwise this call has + * no effect.</p> * - * Incompatible with {@link #HARDWARE_ALLOCATOR}. Trying to combine them - * will throw an {@link java.lang.IllegalStateException}. + * <p>setAsAlphaMask is incompatible with {@link #ALLOCATOR_HARDWARE}. Trying to + * combine them will result in {@link #decodeDrawable}/ + * {@link #decodeBitmap} throwing an + * {@link java.lang.IllegalStateException}.</p> */ - public void setAsAlphaMask() { - mAsAlphaMask = true; + public void setAsAlphaMask(boolean asAlphaMask) { + mAsAlphaMask = asAlphaMask; } @Override @@ -739,7 +812,7 @@ public final class ImageDecoder implements AutoCloseable { checkSubset(mDesiredWidth, mDesiredHeight, mCropRect); - if (mAllocator == HARDWARE_ALLOCATOR) { + if (mAllocator == ALLOCATOR_HARDWARE) { if (mMutable) { throw new IllegalStateException("Cannot make mutable HARDWARE Bitmap!"); } @@ -748,7 +821,7 @@ public final class ImageDecoder implements AutoCloseable { } } - if (mPostProcess != null && mRequireUnpremultiplied) { + if (mPostProcessor != null && mRequireUnpremultiplied) { throw new IllegalStateException("Cannot draw to unpremultiplied pixels!"); } } @@ -763,18 +836,34 @@ public final class ImageDecoder implements AutoCloseable { } } + @NonNull private Bitmap decodeBitmap() throws IOException { checkState(); - // nDecodeBitmap calls postProcessAndRelease only if mPostProcess + // nDecodeBitmap calls onPartialImage only if mOnPartialImageListener + // exists + ImageDecoder partialImagePtr = mOnPartialImageListener == null ? null : this; + // nDecodeBitmap calls postProcessAndRelease only if mPostProcessor // exists. - ImageDecoder postProcessPtr = mPostProcess == null ? null : this; - return nDecodeBitmap(mNativePtr, mOnPartialImageListener, + ImageDecoder postProcessPtr = mPostProcessor == null ? null : this; + return nDecodeBitmap(mNativePtr, partialImagePtr, postProcessPtr, mDesiredWidth, mDesiredHeight, mCropRect, mMutable, mAllocator, mRequireUnpremultiplied, mPreferRamOverQuality, mAsAlphaMask); } + private void callHeaderDecoded(@Nullable OnHeaderDecodedListener listener, + @NonNull Source src) { + if (listener != null) { + ImageInfo info = new ImageInfo(this); + try { + listener.onHeaderDecoded(this, info, src); + } finally { + info.mDecoder = null; + } + } + } + /** * Create a {@link Drawable} from a {@code Source}. * @@ -791,14 +880,8 @@ public final class ImageDecoder implements AutoCloseable { public static Drawable decodeDrawable(@NonNull Source src, @Nullable OnHeaderDecodedListener listener) throws IOException { try (ImageDecoder decoder = src.createImageDecoder()) { - if (listener != null) { - ImageInfo info = new ImageInfo(decoder); - try { - listener.onHeaderDecoded(info, decoder); - } finally { - info.decoder = null; - } - } + decoder.mSource = src; + decoder.callHeaderDecoded(listener, src); if (decoder.mRequireUnpremultiplied) { // Though this could be supported (ignored) for opaque images, @@ -817,8 +900,8 @@ public final class ImageDecoder implements AutoCloseable { final int srcDensity = computeDensity(src, decoder); if (decoder.mAnimated) { // AnimatedImageDrawable calls postProcessAndRelease only if - // mPostProcess exists. - ImageDecoder postProcessPtr = decoder.mPostProcess == null ? + // mPostProcessor exists. + ImageDecoder postProcessPtr = decoder.mPostProcessor == null ? null : decoder; Drawable d = new AnimatedImageDrawable(decoder.mNativePtr, postProcessPtr, decoder.mDesiredWidth, @@ -878,14 +961,8 @@ public final class ImageDecoder implements AutoCloseable { public static Bitmap decodeBitmap(@NonNull Source src, @Nullable OnHeaderDecodedListener listener) throws IOException { try (ImageDecoder decoder = src.createImageDecoder()) { - if (listener != null) { - ImageInfo info = new ImageInfo(decoder); - try { - listener.onHeaderDecoded(info, decoder); - } finally { - info.decoder = null; - } - } + decoder.mSource = src; + decoder.callHeaderDecoded(listener, src); // this call potentially manipulates the decoder so it must be performed prior to // decoding the bitmap @@ -922,13 +999,14 @@ public final class ImageDecoder implements AutoCloseable { float scale = (float) dstDensity / srcDensity; int scaledWidth = (int) (decoder.mWidth * scale + 0.5f); int scaledHeight = (int) (decoder.mHeight * scale + 0.5f); - decoder.resize(scaledWidth, scaledHeight); + decoder.setResize(scaledWidth, scaledHeight); return dstDensity; } return srcDensity; } + @NonNull private String getMimeType() { return nGetMimeType(mNativePtr); } @@ -945,14 +1023,22 @@ public final class ImageDecoder implements AutoCloseable { * Private method called by JNI. */ @SuppressWarnings("unused") - private int postProcessAndRelease(@NonNull Canvas canvas, int width, int height) { + private int postProcessAndRelease(@NonNull Canvas canvas) { try { - return mPostProcess.postProcess(canvas, width, height); + return mPostProcessor.onPostProcess(canvas); } finally { canvas.release(); } } + /** + * Private method called by JNI. + */ + @SuppressWarnings("unused") + private boolean onPartialImage(@Error int error) { + return mOnPartialImageListener.onPartialImage(error, mSource); + } + private static native ImageDecoder nCreate(long asset) throws IOException; private static native ImageDecoder nCreate(ByteBuffer buffer, int position, @@ -960,19 +1046,20 @@ public final class ImageDecoder implements AutoCloseable { private static native ImageDecoder nCreate(byte[] data, int offset, int length) throws IOException; private static native ImageDecoder nCreate(InputStream is, byte[] storage); + // The fd must be seekable. private static native ImageDecoder nCreate(FileDescriptor fd) throws IOException; @NonNull private static native Bitmap nDecodeBitmap(long nativePtr, - OnPartialImageListener listener, - @Nullable ImageDecoder decoder, // Only used if mPostProcess != null + @Nullable ImageDecoder partialImageListener, + @Nullable ImageDecoder postProcessor, int width, int height, - Rect cropRect, boolean mutable, + @Nullable Rect cropRect, boolean mutable, int allocator, boolean requireUnpremul, boolean preferRamOverQuality, boolean asAlphaMask) throws IOException; - private static native Point nGetSampledSize(long nativePtr, - int sampleSize); - private static native void nGetPadding(long nativePtr, Rect outRect); + private static native Size nGetSampledSize(long nativePtr, + int sampleSize); + private static native void nGetPadding(long nativePtr, @NonNull Rect outRect); private static native void nClose(long nativePtr); private static native String nGetMimeType(long nativePtr); } diff --git a/graphics/java/android/graphics/PostProcess.java b/graphics/java/android/graphics/PostProcessor.java index c5a31e828c97..b1712e92e2fe 100644 --- a/graphics/java/android/graphics/PostProcess.java +++ b/graphics/java/android/graphics/PostProcessor.java @@ -20,38 +20,38 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.graphics.drawable.Drawable; - /** * Helper interface for adding custom processing to an image. * - * The image being processed may be a {@link Drawable}, {@link Bitmap} or frame + * <p>The image being processed may be a {@link Drawable}, {@link Bitmap} or frame * of an animated image produced by {@link ImageDecoder}. This is called before - * the requested object is returned. + * the requested object is returned.</p> * - * This custom processing also applies to image types that are otherwise - * immutable, such as {@link Bitmap.Config#HARDWARE}. + * <p>This custom processing also applies to image types that are otherwise + * immutable, such as {@link Bitmap.Config#HARDWARE}.</p> * - * On an animated image, the callback will only be called once, but the drawing + * <p>On an animated image, the callback will only be called once, but the drawing * commands will be applied to each frame, as if the {@code Canvas} had been - * returned by {@link Picture#beginRecording}. + * returned by {@link Picture#beginRecording}.<p> * - * Supplied to ImageDecoder via {@link ImageDecoder#setPostProcess}. - * @hide + * <p>Supplied to ImageDecoder via {@link ImageDecoder#setPostProcessor}.</p> */ -public interface PostProcess { +public interface PostProcessor { /** * Do any processing after (for example) decoding. * - * Drawing to the {@link Canvas} will behave as if the initial processing + * <p>Drawing to the {@link Canvas} will behave as if the initial processing * (e.g. decoding) already exists in the Canvas. An implementation can draw * effects on top of this, or it can even draw behind it using * {@link PorterDuff.Mode#DST_OVER}. A common effect is to add transparency * to the corners to achieve rounded corners. That can be done with the - * following code: + * following code:</p> * * <code> * Path path = new Path(); * path.setFillType(Path.FillType.INVERSE_EVEN_ODD); + * int width = canvas.getWidth(); + * int height = canvas.getHeight(); * path.addRoundRect(0, 0, width, height, 20, 20, Path.Direction.CW); * Paint paint = new Paint(); * paint.setAntiAlias(true); @@ -63,10 +63,6 @@ public interface PostProcess { * * * @param canvas The {@link Canvas} to draw to. - * @param width Width of {@code canvas}. Anything drawn outside of this - * will be ignored. - * @param height Height of {@code canvas}. Anything drawn outside of this - * will be ignored. * @return Opacity of the result after drawing. * {@link PixelFormat#UNKNOWN} means that the implementation did not * change whether the image has alpha. Return this unless you added @@ -87,5 +83,5 @@ public interface PostProcess { * {@link java.lang.IllegalArgumentException}. */ @PixelFormat.Opacity - public int postProcess(@NonNull Canvas canvas, int width, int height); + public int onPostProcess(@NonNull Canvas canvas); } diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java index f74c39d84bce..3a5f7b73e196 100644 --- a/graphics/java/android/graphics/drawable/BitmapDrawable.java +++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java @@ -165,8 +165,8 @@ public class BitmapDrawable extends Drawable { Bitmap bitmap = null; try (FileInputStream stream = new FileInputStream(filepath)) { bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(res, stream), - (info, decoder) -> { - decoder.setAllocator(ImageDecoder.SOFTWARE_ALLOCATOR); + (decoder, info, src) -> { + decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE); }); } catch (Exception e) { /* do nothing. This matches the behavior of BitmapFactory.decodeFile() @@ -198,8 +198,8 @@ public class BitmapDrawable extends Drawable { Bitmap bitmap = null; try { bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(res, is), - (info, decoder) -> { - decoder.setAllocator(ImageDecoder.SOFTWARE_ALLOCATOR); + (decoder, info, src) -> { + decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE); }); } catch (Exception e) { /* do nothing. This matches the behavior of BitmapFactory.decodeStream() @@ -838,8 +838,8 @@ public class BitmapDrawable extends Drawable { Bitmap bitmap = null; try (InputStream is = r.openRawResource(srcResId, value)) { ImageDecoder.Source source = ImageDecoder.createSource(r, is, density); - bitmap = ImageDecoder.decodeBitmap(source, (info, decoder) -> { - decoder.setAllocator(ImageDecoder.SOFTWARE_ALLOCATOR); + bitmap = ImageDecoder.decodeBitmap(source, (decoder, info, src) -> { + decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE); }); } catch (Exception e) { // Do nothing and pick up the error below. diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java index 291b0a0be4f4..36a4d26d62bb 100644 --- a/graphics/java/android/graphics/drawable/Drawable.java +++ b/graphics/java/android/graphics/drawable/Drawable.java @@ -1229,8 +1229,8 @@ public abstract class Drawable { source = ImageDecoder.createSource(res, is); } - return ImageDecoder.decodeDrawable(source, (info, decoder) -> { - decoder.setAllocator(ImageDecoder.SOFTWARE_ALLOCATOR); + return ImageDecoder.decodeDrawable(source, (decoder, info, src) -> { + decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE); }); } catch (IOException e) { /* do nothing. diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp index 5b95c81db24e..696a00c7b2c0 100644 --- a/libs/androidfw/ResourceTypes.cpp +++ b/libs/androidfw/ResourceTypes.cpp @@ -1877,19 +1877,27 @@ void ResTable_config::swapHtoD() { return (l.locale > r.locale) ? 1 : -1; } - // The language & region are equal, so compare the scripts and variants. + // The language & region are equal, so compare the scripts, variants and + // numbering systms in this order. Comparison of variants and numbering + // systems should happen very infrequently (if at all.) + // The comparison code relies on memcmp low-level optimizations that make it + // more efficient than strncmp. const char emptyScript[sizeof(l.localeScript)] = {'\0', '\0', '\0', '\0'}; const char *lScript = l.localeScriptWasComputed ? emptyScript : l.localeScript; const char *rScript = r.localeScriptWasComputed ? emptyScript : r.localeScript; + int script = memcmp(lScript, rScript, sizeof(l.localeScript)); if (script) { return script; } - // The language, region and script are equal, so compare variants. - // - // This should happen very infrequently (if at all.) - return memcmp(l.localeVariant, r.localeVariant, sizeof(l.localeVariant)); + int variant = memcmp(l.localeVariant, r.localeVariant, sizeof(l.localeVariant)); + if (variant) { + return variant; + } + + return memcmp(l.localeNumberingSystem, r.localeNumberingSystem, + sizeof(l.localeNumberingSystem)); } int ResTable_config::compare(const ResTable_config& o) const { @@ -2030,6 +2038,22 @@ int ResTable_config::diff(const ResTable_config& o) const { return diffs; } +// There isn't a well specified "importance" order between variants and +// scripts. We can't easily tell whether, say "en-Latn-US" is more or less +// specific than "en-US-POSIX". +// +// We therefore arbitrarily decide to give priority to variants over +// scripts since it seems more useful to do so. We will consider +// "en-US-POSIX" to be more specific than "en-Latn-US". +// +// Unicode extension keywords are considered to be less important than +// scripts and variants. +inline int ResTable_config::getImportanceScoreOfLocale() const { + return (localeVariant[0] ? 4 : 0) + + (localeScript[0] && !localeScriptWasComputed ? 2: 0) + + (localeNumberingSystem[0] ? 1: 0); +} + int ResTable_config::isLocaleMoreSpecificThan(const ResTable_config& o) const { if (locale || o.locale) { if (language[0] != o.language[0]) { @@ -2043,21 +2067,7 @@ int ResTable_config::isLocaleMoreSpecificThan(const ResTable_config& o) const { } } - // There isn't a well specified "importance" order between variants and - // scripts. We can't easily tell whether, say "en-Latn-US" is more or less - // specific than "en-US-POSIX". - // - // We therefore arbitrarily decide to give priority to variants over - // scripts since it seems more useful to do so. We will consider - // "en-US-POSIX" to be more specific than "en-Latn-US". - - const int score = ((localeScript[0] != '\0' && !localeScriptWasComputed) ? 1 : 0) + - ((localeVariant[0] != '\0') ? 2 : 0); - - const int oScore = (o.localeScript[0] != '\0' && !o.localeScriptWasComputed ? 1 : 0) + - ((o.localeVariant[0] != '\0') ? 2 : 0); - - return score - oScore; + return getImportanceScoreOfLocale() - o.getImportanceScoreOfLocale(); } bool ResTable_config::isMoreSpecificThan(const ResTable_config& o) const { @@ -2314,6 +2324,17 @@ bool ResTable_config::isLocaleBetterThan(const ResTable_config& o, return localeMatches; } + // The variants are the same, try numbering system. + const bool localeNumsysMatches = strncmp(localeNumberingSystem, + requested->localeNumberingSystem, + sizeof(localeNumberingSystem)) == 0; + const bool otherNumsysMatches = strncmp(o.localeNumberingSystem, + requested->localeNumberingSystem, + sizeof(localeNumberingSystem)) == 0; + if (localeNumsysMatches != otherNumsysMatches) { + return localeNumsysMatches; + } + // Finally, the languages, although equivalent, may still be different // (like for Tagalog and Filipino). Identical is better than just // equivalent. @@ -2781,7 +2802,7 @@ void ResTable_config::appendDirLocale(String8& out) const { return; } const bool scriptWasProvided = localeScript[0] != '\0' && !localeScriptWasComputed; - if (!scriptWasProvided && !localeVariant[0]) { + if (!scriptWasProvided && !localeVariant[0] && !localeNumberingSystem[0]) { // Legacy format. if (out.size() > 0) { out.append("-"); @@ -2826,6 +2847,12 @@ void ResTable_config::appendDirLocale(String8& out) const { out.append("+"); out.append(localeVariant, strnlen(localeVariant, sizeof(localeVariant))); } + + if (localeNumberingSystem[0]) { + out.append("+u+nu+"); + out.append(localeNumberingSystem, + strnlen(localeNumberingSystem, sizeof(localeNumberingSystem))); + } } void ResTable_config::getBcp47Locale(char str[RESTABLE_MAX_LOCALE_LEN], bool canonicalize) const { @@ -2868,10 +2895,17 @@ void ResTable_config::getBcp47Locale(char str[RESTABLE_MAX_LOCALE_LEN], bool can str[charsWritten++] = '-'; } memcpy(str + charsWritten, localeVariant, sizeof(localeVariant)); + charsWritten += strnlen(str + charsWritten, sizeof(localeVariant)); } - /* TODO: Add BCP47 extension. It requires RESTABLE_MAX_LOCALE_LEN - * increase from 28 to 42 bytes (-u-nu-xxxxxxxx) */ + // Add Unicode extension only if at least one other locale component is present + if (localeNumberingSystem[0] != '\0' && charsWritten > 0) { + static constexpr char NU_PREFIX[] = "-u-nu-"; + static constexpr size_t NU_PREFIX_LEN = sizeof(NU_PREFIX) - 1; + memcpy(str + charsWritten, NU_PREFIX, NU_PREFIX_LEN); + charsWritten += NU_PREFIX_LEN; + memcpy(str + charsWritten, localeNumberingSystem, sizeof(localeNumberingSystem)); + } } struct LocaleParserState { @@ -3004,10 +3038,7 @@ struct LocaleParserState { } void ResTable_config::setBcp47Locale(const char* in) { - locale = 0; - memset(localeScript, 0, sizeof(localeScript)); - memset(localeVariant, 0, sizeof(localeVariant)); - memset(localeNumberingSystem, 0, sizeof(localeNumberingSystem)); + clearLocale(); const char* start = in; LocaleParserState state; diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h index 8cf4de9167e5..a1f15f0c96cb 100644 --- a/libs/androidfw/include/androidfw/ResourceTypes.h +++ b/libs/androidfw/include/androidfw/ResourceTypes.h @@ -894,9 +894,10 @@ struct ResTable_package // - a 8 char variant code prefixed by a 'v' // // each separated by a single char separator, which sums up to a total of 24 -// chars, (25 include the string terminator) rounded up to 28 to be 4 byte -// aligned. -#define RESTABLE_MAX_LOCALE_LEN 28 +// chars, (25 include the string terminator). Numbering system specificator, +// if present, can add up to 14 bytes (-u-nu-xxxxxxxx), giving 39 bytes, +// or 40 bytes to make it 4 bytes aligned. +#define RESTABLE_MAX_LOCALE_LEN 40 /** @@ -1303,6 +1304,9 @@ struct ResTable_config // and 0 if they're equally specific. int isLocaleMoreSpecificThan(const ResTable_config &o) const; + // Returns an integer representng the imporance score of the configuration locale. + int getImportanceScoreOfLocale() const; + // Return true if 'this' is a better locale match than 'o' for the // 'requested' configuration. Similar to isBetterThan(), this assumes that // match() has already been used to remove any configurations that don't diff --git a/libs/androidfw/tests/ConfigLocale_test.cpp b/libs/androidfw/tests/ConfigLocale_test.cpp index 35007c815edd..ac08c52772d1 100644 --- a/libs/androidfw/tests/ConfigLocale_test.cpp +++ b/libs/androidfw/tests/ConfigLocale_test.cpp @@ -173,6 +173,18 @@ TEST(ConfigLocaleTest, IsMoreSpecificThan) { fillIn("en", "US", NULL, "POSIX", &r); EXPECT_FALSE(l.isMoreSpecificThan(r)); EXPECT_TRUE(r.isMoreSpecificThan(l)); + + fillIn("ar", "EG", NULL, NULL, &l); + fillIn("ar", "EG", NULL, NULL, &r); + memcpy(&r.localeNumberingSystem, "latn", 4); + EXPECT_FALSE(l.isMoreSpecificThan(r)); + EXPECT_TRUE(r.isMoreSpecificThan(l)); + + fillIn("en", "US", NULL, NULL, &l); + fillIn("es", "ES", NULL, NULL, &r); + + EXPECT_FALSE(l.isMoreSpecificThan(r)); + EXPECT_FALSE(r.isMoreSpecificThan(l)); } TEST(ConfigLocaleTest, setLocale) { @@ -321,6 +333,22 @@ TEST(ConfigLocaleTest, getBcp47Locale_script) { EXPECT_EQ(0, strcmp("en", out)); } +TEST(ConfigLocaleTest, getBcp47Locale_numberingSystem) { + ResTable_config config; + fillIn("en", NULL, NULL, NULL, &config); + + char out[RESTABLE_MAX_LOCALE_LEN]; + + memcpy(&config.localeNumberingSystem, "latn", 4); + config.getBcp47Locale(out); + EXPECT_EQ(0, strcmp("en-u-nu-latn", out)); + + fillIn("sr", "SR", "Latn", NULL, &config); + memcpy(&config.localeNumberingSystem, "latn", 4); + config.getBcp47Locale(out); + EXPECT_EQ(0, strcmp("sr-Latn-SR-u-nu-latn", out)); +} + TEST(ConfigLocaleTest, getBcp47Locale_canonicalize) { ResTable_config config; char out[RESTABLE_MAX_LOCALE_LEN]; @@ -433,6 +461,11 @@ TEST(ConfigLocaleTest, match) { fillIn("ar", "XB", NULL, NULL, &requested); // Even if they are pseudo-locales, exactly equal locales match. EXPECT_TRUE(supported.match(requested)); + + fillIn("ar", "EG", NULL, NULL, &supported); + fillIn("ar", "TN", NULL, NULL, &requested); + memcpy(&supported.localeNumberingSystem, "latn", 4); + EXPECT_TRUE(supported.match(requested)); } TEST(ConfigLocaleTest, match_emptyScript) { @@ -758,6 +791,26 @@ TEST(ConfigLocaleTest, isLocaleBetterThan_regionComparison) { EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); } +TEST(ConfigLocaleTest, isLocaleBetterThan_numberingSystem) { + ResTable_config config1, config2, request; + + fillIn("ar", "EG", NULL, NULL, &request); + memcpy(&request.localeNumberingSystem, "latn", 4); + fillIn("ar", NULL, NULL, NULL, &config1); + memcpy(&config1.localeNumberingSystem, "latn", 4); + fillIn("ar", NULL, NULL, NULL, &config2); + EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request)); + EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request)); + + fillIn("ar", "EG", NULL, NULL, &request); + memcpy(&request.localeNumberingSystem, "latn", 4); + fillIn("ar", "TN", NULL, NULL, &config1); + memcpy(&config1.localeNumberingSystem, "latn", 4); + fillIn("ar", NULL, NULL, NULL, &config2); + EXPECT_TRUE(config2.isLocaleBetterThan(config1, &request)); + EXPECT_FALSE(config1.isLocaleBetterThan(config2, &request)); +} + // Default resources are considered better matches for US English // and US-like English locales than International English locales TEST(ConfigLocaleTest, isLocaleBetterThan_UsEnglishIsSpecial) { diff --git a/media/java/android/media/AudioFocusRequest.java b/media/java/android/media/AudioFocusRequest.java index de59ac39abf6..7104dad4dc4c 100644 --- a/media/java/android/media/AudioFocusRequest.java +++ b/media/java/android/media/AudioFocusRequest.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.media.AudioManager.OnAudioFocusChangeListener; +import android.os.Bundle; import android.os.Handler; import android.os.Looper; @@ -220,6 +221,9 @@ public final class AudioFocusRequest { private final static AudioAttributes FOCUS_DEFAULT_ATTR = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_MEDIA).build(); + /** @hide */ + public static final String KEY_ACCESSIBILITY_FORCE_FOCUS_DUCKING = "a11y_force_ducking"; + private final OnAudioFocusChangeListener mFocusListener; // may be null private final Handler mListenerHandler; // may be null private final AudioAttributes mAttr; // never null @@ -349,6 +353,7 @@ public final class AudioFocusRequest { private boolean mPausesOnDuck = false; private boolean mDelayedFocus = false; private boolean mFocusLocked = false; + private boolean mA11yForceDucking = false; /** * Constructs a new {@code Builder}, and specifies how audio focus @@ -526,6 +531,21 @@ public final class AudioFocusRequest { } /** + * Marks this focus request as forcing ducking, regardless of the conditions in which + * the system would or would not enforce ducking. + * Forcing ducking will only be honored when requesting AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK + * with an {@link AudioAttributes} usage of + * {@link AudioAttributes#USAGE_ASSISTANCE_ACCESSIBILITY}, coming from an accessibility + * service, and will be ignored otherwise. + * @param forceDucking {@code true} to force ducking + * @return this {@code Builder} instance + */ + public @NonNull Builder setForceDucking(boolean forceDucking) { + mA11yForceDucking = forceDucking; + return this; + } + + /** * Builds a new {@code AudioFocusRequest} instance combining all the information gathered * by this {@code Builder}'s configuration methods. * @return the {@code AudioFocusRequest} instance qualified by all the properties set @@ -538,6 +558,17 @@ public final class AudioFocusRequest { throw new IllegalStateException( "Can't use delayed focus or pause on duck without a listener"); } + if (mA11yForceDucking) { + final Bundle extraInfo; + if (mAttr.getBundle() == null) { + extraInfo = new Bundle(); + } else { + extraInfo = mAttr.getBundle(); + } + // checking of usage and focus request is done server side + extraInfo.putBoolean(KEY_ACCESSIBILITY_FORCE_FOCUS_DUCKING, true); + mAttr = new AudioAttributes.Builder(mAttr).addBundle(extraInfo).build(); + } final int flags = 0 | (mDelayedFocus ? AudioManager.AUDIOFOCUS_FLAG_DELAY_OK : 0) | (mPausesOnDuck ? AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS : 0) diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java index e2f9b47ed482..690d74040ce1 100644 --- a/media/java/android/media/MediaDrm.java +++ b/media/java/android/media/MediaDrm.java @@ -16,13 +16,6 @@ package android.media; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.UUID; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -34,6 +27,16 @@ import android.os.Looper; import android.os.Message; import android.os.Parcel; import android.util.Log; +import dalvik.system.CloseGuard; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicBoolean; + /** * MediaDrm can be used to obtain keys for decrypting protected media streams, in @@ -117,10 +120,13 @@ import android.util.Log; * MediaDrm objects on a thread with its own Looper running (main UI * thread by default has a Looper running). */ -public final class MediaDrm { +public final class MediaDrm implements AutoCloseable { private static final String TAG = "MediaDrm"; + private final AtomicBoolean mClosed = new AtomicBoolean(); + private final CloseGuard mCloseGuard = CloseGuard.get(); + private static final String PERMISSION = android.Manifest.permission.ACCESS_DRM_CERTIFICATES; private EventHandler mEventHandler; @@ -215,6 +221,8 @@ public final class MediaDrm { */ native_setup(new WeakReference<MediaDrm>(this), getByteArrayFromUUID(uuid), ActivityThread.currentOpPackageName()); + + mCloseGuard.open("release"); } /** @@ -954,6 +962,168 @@ public final class MediaDrm { */ public native void releaseAllSecureStops(); + @Retention(RetentionPolicy.SOURCE) + @IntDef({HDCP_LEVEL_UNKNOWN, HDCP_NONE, HDCP_V1, HDCP_V2, + HDCP_V2_1, HDCP_V2_2, HDCP_NO_DIGITAL_OUTPUT}) + public @interface HdcpLevel {} + + + /** + * The DRM plugin did not report an HDCP level, or an error + * occurred accessing it + */ + public static final int HDCP_LEVEL_UNKNOWN = 0; + + /** + * HDCP is not supported on this device, content is unprotected + */ + public static final int HDCP_NONE = 1; + + /** + * HDCP version 1.0 + */ + public static final int HDCP_V1 = 2; + + /** + * HDCP version 2.0 Type 1. + */ + public static final int HDCP_V2 = 3; + + /** + * HDCP version 2.1 Type 1. + */ + public static final int HDCP_V2_1 = 4; + + /** + * HDCP version 2.2 Type 1. + */ + public static final int HDCP_V2_2 = 5; + + /** + * No digital output, implicitly secure + */ + public static final int HDCP_NO_DIGITAL_OUTPUT = Integer.MAX_VALUE; + + /** + * Return the HDCP level negotiated with downstream receivers the + * device is connected to. If multiple HDCP-capable displays are + * simultaneously connected to separate interfaces, this method + * returns the lowest negotiated level of all interfaces. + * <p> + * This method should only be used for informational purposes, not for + * enforcing compliance with HDCP requirements. Trusted enforcement of + * HDCP policies must be handled by the DRM system. + * <p> + * @return one of {@link #HDCP_LEVEL_UNKNOWN}, {@link #HDCP_NONE}, + * {@link #HDCP_V1}, {@link #HDCP_V2}, {@link #HDCP_V2_1}, {@link #HDCP_V2_2} + * or {@link #HDCP_NO_DIGITAL_OUTPUT}. + */ + @HdcpLevel + public native int getConnectedHdcpLevel(); + + /** + * Return the maximum supported HDCP level. The maximum HDCP level is a + * constant for a given device, it does not depend on downstream receivers + * that may be connected. If multiple HDCP-capable interfaces are present, + * it indicates the highest of the maximum HDCP levels of all interfaces. + * <p> + * @return one of {@link #HDCP_LEVEL_UNKNOWN}, {@link #HDCP_NONE}, + * {@link #HDCP_V1}, {@link #HDCP_V2}, {@link #HDCP_V2_1}, {@link #HDCP_V2_2} + * or {@link #HDCP_NO_DIGITAL_OUTPUT}. + */ + @HdcpLevel + public native int getMaxHdcpLevel(); + + /** + * Return the number of MediaDrm sessions that are currently opened + * simultaneously among all MediaDrm instances for the active DRM scheme. + * @return the number of open sessions. + */ + public native int getOpenSessionCount(); + + /** + * Return the maximum number of MediaDrm sessions that may be opened + * simultaneosly among all MediaDrm instances for the active DRM + * scheme. The maximum number of sessions is not affected by any + * sessions that may have already been opened. + * @return maximum sessions. + */ + public native int getMaxSessionCount(); + + /** + * Security level indicates the robustness of the device's DRM + * implementation. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({SECURITY_LEVEL_UNKNOWN, SW_SECURE_CRYPTO, SW_SECURE_DECODE, + HW_SECURE_CRYPTO, HW_SECURE_DECODE, HW_SECURE_ALL}) + public @interface SecurityLevel {} + + /** + * The DRM plugin did not report a security level, or an error occurred + * accessing it + */ + public static final int SECURITY_LEVEL_UNKNOWN = 0; + + /** + * Software-based whitebox crypto + */ + public static final int SW_SECURE_CRYPTO = 1; + + /** + * Software-based whitebox crypto and an obfuscated decoder + */ + public static final int SW_SECURE_DECODE = 2; + + /** + * DRM key management and crypto operations are performed within a + * hardware backed trusted execution environment + */ + public static final int HW_SECURE_CRYPTO = 3; + + /** + * DRM key management, crypto operations and decoding of content + * are performed within a hardware backed trusted execution environment + */ + public static final int HW_SECURE_DECODE = 4; + + /** + * DRM key management, crypto operations, decoding of content and all + * handling of the media (compressed and uncompressed) is handled within + * a hardware backed trusted execution environment. + */ + public static final int HW_SECURE_ALL = 5; + + /** + * Return the current security level of a session. A session + * has an initial security level determined by the robustness of + * the DRM system's implementation on the device. The security + * level may be adjusted using {@link #setSecurityLevel}. + * @param sessionId the session to query. + * <p> + * @return one of {@link #SECURITY_LEVEL_UNKNOWN}, + * {@link #SW_SECURE_CRYPTO}, {@link #SW_SECURE_DECODE}, + * {@link #HW_SECURE_CRYPTO}, {@link #HW_SECURE_DECODE} or + * {@link #HW_SECURE_ALL}. + */ + @SecurityLevel + public native int getSecurityLevel(@NonNull byte[] sessionId); + + /** + * Set the security level of a session. This can be useful if specific + * attributes of a lower security level are needed by an application, + * such as image manipulation or compositing. Reducing the security + * level will typically limit decryption to lower content resolutions, + * depending on the license policy. + * @param sessionId the session to set the security level on. + * @param level the new security level, one of + * {@link #SW_SECURE_CRYPTO}, {@link #SW_SECURE_DECODE}, + * {@link #HW_SECURE_CRYPTO}, {@link #HW_SECURE_DECODE} or + * {@link #HW_SECURE_ALL}. + */ + public native void setSecurityLevel(@NonNull byte[] sessionId, + @SecurityLevel int level); + /** * String property name: identifies the maker of the DRM plugin */ @@ -1311,18 +1481,52 @@ public final class MediaDrm { } @Override - protected void finalize() { - native_finalize(); + protected void finalize() throws Throwable { + try { + if (mCloseGuard != null) { + mCloseGuard.warnIfOpen(); + } + release(); + } finally { + super.finalize(); + } } - public native final void release(); + /** + * Releases resources associated with the current session of + * MediaDrm. It is considered good practice to call this method when + * the {@link MediaDrm} object is no longer needed in your + * application. After this method is called, {@link MediaDrm} is no + * longer usable since it has lost all of its required resource. + * + * This method was added in API 28. In API versions 18 through 27, release() + * should be called instead. There is no need to do anything for API + * versions prior to 18. + */ + @Override + public void close() { + release(); + } + + /** + * @deprecated replaced by {@link #close()}. + */ + @Deprecated + public void release() { + mCloseGuard.close(); + if (mClosed.compareAndSet(false, true)) { + native_release(); + } + } + + /** @hide */ + public native final void native_release(); + private static native final void native_init(); private native final void native_setup(Object mediadrm_this, byte[] uuid, String appPackageName); - private native final void native_finalize(); - static { System.loadLibrary("media_jni"); native_init(); diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp index 51c9e5f1c7da..1dddbeed608c 100644 --- a/media/jni/android_media_MediaDrm.cpp +++ b/media/jni/android_media_MediaDrm.cpp @@ -130,6 +130,26 @@ struct StateExceptionFields { jclass classId; }; +struct HDCPLevels { + jint kHdcpLevelUnknown; + jint kHdcpNone; + jint kHdcpV1; + jint kHdcpV2; + jint kHdcpV2_1; + jint kHdcpV2_2; + jint kHdcpNoOutput; +} gHdcpLevels; + +struct SecurityLevels { + jint kSecurityLevelUnknown; + jint kSecurityLevelSwSecureCrypto; + jint kSecurityLevelSwSecureDecode; + jint kSecurityLevelHwSecureCrypto; + jint kSecurityLevelHwSecureDecode; + jint kSecurityLevelHwSecureAll; +} gSecurityLevels; + + struct fields_t { jfieldID context; jmethodID post_event; @@ -565,12 +585,19 @@ static sp<JDrm> setDrm( return old; } -static bool CheckSession(JNIEnv *env, const sp<IDrm> &drm, jbyteArray const &jsessionId) -{ +static bool CheckDrm(JNIEnv *env, const sp<IDrm> &drm) { if (drm == NULL) { jniThrowException(env, "java/lang/IllegalStateException", "MediaDrm obj is null"); return false; } + return true; +} + +static bool CheckSession(JNIEnv *env, const sp<IDrm> &drm, jbyteArray const &jsessionId) +{ + if (!CheckDrm(env, drm)) { + return false; + } if (jsessionId == NULL) { jniThrowException(env, "java/lang/IllegalArgumentException", "sessionId is null"); @@ -579,7 +606,7 @@ static bool CheckSession(JNIEnv *env, const sp<IDrm> &drm, jbyteArray const &jse return true; } -static void android_media_MediaDrm_release(JNIEnv *env, jobject thiz) { +static void android_media_MediaDrm_native_release(JNIEnv *env, jobject thiz) { sp<JDrm> drm = setDrm(env, thiz, NULL); if (drm != NULL) { drm->setListener(NULL); @@ -625,6 +652,34 @@ static void android_media_MediaDrm_native_init(JNIEnv *env) { GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_X509", "I"); gCertificateTypes.kCertificateTypeX509 = env->GetStaticIntField(clazz, field); + GET_STATIC_FIELD_ID(field, clazz, "HDCP_LEVEL_UNKNOWN", "I"); + gHdcpLevels.kHdcpLevelUnknown = env->GetStaticIntField(clazz, field); + GET_STATIC_FIELD_ID(field, clazz, "HDCP_NONE", "I"); + gHdcpLevels.kHdcpNone = env->GetStaticIntField(clazz, field); + GET_STATIC_FIELD_ID(field, clazz, "HDCP_V1", "I"); + gHdcpLevels.kHdcpV1 = env->GetStaticIntField(clazz, field); + GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2", "I"); + gHdcpLevels.kHdcpV2 = env->GetStaticIntField(clazz, field); + GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_1", "I"); + gHdcpLevels.kHdcpV2_1 = env->GetStaticIntField(clazz, field); + GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_2", "I"); + gHdcpLevels.kHdcpV2_2 = env->GetStaticIntField(clazz, field); + GET_STATIC_FIELD_ID(field, clazz, "HDCP_NO_DIGITAL_OUTPUT", "I"); + gHdcpLevels.kHdcpNoOutput = env->GetStaticIntField(clazz, field); + + GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_UNKNOWN", "I"); + gSecurityLevels.kSecurityLevelUnknown = env->GetStaticIntField(clazz, field); + GET_STATIC_FIELD_ID(field, clazz, "SW_SECURE_CRYPTO", "I"); + gSecurityLevels.kSecurityLevelSwSecureCrypto = env->GetStaticIntField(clazz, field); + GET_STATIC_FIELD_ID(field, clazz, "SW_SECURE_DECODE", "I"); + gSecurityLevels.kSecurityLevelSwSecureDecode = env->GetStaticIntField(clazz, field); + GET_STATIC_FIELD_ID(field, clazz, "HW_SECURE_CRYPTO", "I"); + gSecurityLevels.kSecurityLevelHwSecureCrypto = env->GetStaticIntField(clazz, field); + GET_STATIC_FIELD_ID(field, clazz, "HW_SECURE_DECODE", "I"); + gSecurityLevels.kSecurityLevelHwSecureDecode = env->GetStaticIntField(clazz, field); + GET_STATIC_FIELD_ID(field, clazz, "HW_SECURE_ALL", "I"); + gSecurityLevels.kSecurityLevelHwSecureAll = env->GetStaticIntField(clazz, field); + FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest"); GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B"); GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;"); @@ -724,11 +779,6 @@ static void android_media_MediaDrm_native_setup( setDrm(env, thiz, drm); } -static void android_media_MediaDrm_native_finalize( - JNIEnv *env, jobject thiz) { - android_media_MediaDrm_release(env, thiz); -} - static jboolean android_media_MediaDrm_isCryptoSchemeSupportedNative( JNIEnv *env, jobject /* thiz */, jbyteArray uuidObj, jstring jmimeType) { @@ -971,9 +1021,7 @@ static jobject android_media_MediaDrm_getProvisionRequestNative( JNIEnv *env, jobject thiz, jint jcertType, jstring jcertAuthority) { sp<IDrm> drm = GetDrm(env, thiz); - if (drm == NULL) { - jniThrowException(env, "java/lang/IllegalStateException", - "MediaDrm obj is null"); + if (!CheckDrm(env, drm)) { return NULL; } @@ -1018,9 +1066,7 @@ static jobject android_media_MediaDrm_provideProvisionResponseNative( JNIEnv *env, jobject thiz, jbyteArray jresponse) { sp<IDrm> drm = GetDrm(env, thiz); - if (drm == NULL) { - jniThrowException(env, "java/lang/IllegalStateException", - "MediaDrm obj is null"); + if (!CheckDrm(env, drm)) { return NULL; } @@ -1057,9 +1103,7 @@ static jobject android_media_MediaDrm_getSecureStops( JNIEnv *env, jobject thiz) { sp<IDrm> drm = GetDrm(env, thiz); - if (drm == NULL) { - jniThrowException(env, "java/lang/IllegalStateException", - "MediaDrm obj is null"); + if (!CheckDrm(env, drm)) { return NULL; } @@ -1078,9 +1122,7 @@ static jbyteArray android_media_MediaDrm_getSecureStop( JNIEnv *env, jobject thiz, jbyteArray ssid) { sp<IDrm> drm = GetDrm(env, thiz); - if (drm == NULL) { - jniThrowException(env, "java/lang/IllegalStateException", - "MediaDrm obj is null"); + if (!CheckDrm(env, drm)) { return NULL; } @@ -1099,9 +1141,7 @@ static void android_media_MediaDrm_releaseSecureStops( JNIEnv *env, jobject thiz, jbyteArray jssRelease) { sp<IDrm> drm = GetDrm(env, thiz); - if (drm == NULL) { - jniThrowException(env, "java/lang/IllegalStateException", - "MediaDrm obj is null"); + if (!CheckDrm(env, drm)) { return; } @@ -1116,9 +1156,7 @@ static void android_media_MediaDrm_releaseAllSecureStops( JNIEnv *env, jobject thiz) { sp<IDrm> drm = GetDrm(env, thiz); - if (drm == NULL) { - jniThrowException(env, "java/lang/IllegalStateException", - "MediaDrm obj is null"); + if (!CheckDrm(env, drm)) { return; } @@ -1127,13 +1165,173 @@ static void android_media_MediaDrm_releaseAllSecureStops( throwExceptionAsNecessary(env, err, "Failed to release all secure stops"); } + +static jint HdcpLevelTojint(DrmPlugin::HdcpLevel level) { + switch(level) { + case DrmPlugin::kHdcpLevelUnknown: + return gHdcpLevels.kHdcpLevelUnknown; + case DrmPlugin::kHdcpNone: + return gHdcpLevels.kHdcpNone; + case DrmPlugin::kHdcpV1: + return gHdcpLevels.kHdcpV1; + case DrmPlugin::kHdcpV2: + return gHdcpLevels.kHdcpV2; + case DrmPlugin::kHdcpV2_1: + return gHdcpLevels.kHdcpV2_1; + case DrmPlugin::kHdcpV2_2: + return gHdcpLevels.kHdcpV2_2; + case DrmPlugin::kHdcpNoOutput: + return gHdcpLevels.kHdcpNoOutput; + } + return gHdcpLevels.kHdcpNone; +} + +static jint android_media_MediaDrm_getConnectedHdcpLevel(JNIEnv *env, + jobject thiz) { + sp<IDrm> drm = GetDrm(env, thiz); + + if (!CheckDrm(env, drm)) { + return gHdcpLevels.kHdcpNone; + } + + DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpNone; + DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpNone; + + status_t err = drm->getHdcpLevels(&connected, &max); + + if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) { + return gHdcpLevels.kHdcpLevelUnknown; + } + return HdcpLevelTojint(connected); +} + +static jint android_media_MediaDrm_getMaxHdcpLevel(JNIEnv *env, + jobject thiz) { + sp<IDrm> drm = GetDrm(env, thiz); + + if (!CheckDrm(env, drm)) { + return gHdcpLevels.kHdcpLevelUnknown; + } + + DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpLevelUnknown; + DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpLevelUnknown; + + status_t err = drm->getHdcpLevels(&connected, &max); + + if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) { + return gHdcpLevels.kHdcpLevelUnknown; + } + return HdcpLevelTojint(max); +} + +static jint android_media_MediaDrm_getOpenSessionCount(JNIEnv *env, + jobject thiz) { + sp<IDrm> drm = GetDrm(env, thiz); + + if (!CheckDrm(env, drm)) { + return 0; + } + + uint32_t open = 0, max = 0; + status_t err = drm->getNumberOfSessions(&open, &max); + + if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) { + return 0; + } + return open; +} + +static jint android_media_MediaDrm_getMaxSessionCount(JNIEnv *env, + jobject thiz) { + sp<IDrm> drm = GetDrm(env, thiz); + + if (!CheckDrm(env, drm)) { + return 0; + } + + uint32_t open = 0, max = 0; + status_t err = drm->getNumberOfSessions(&open, &max); + + if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) { + return 0; + } + return max; +} + +static jint android_media_MediaDrm_getSecurityLevel(JNIEnv *env, + jobject thiz, jbyteArray jsessionId) { + sp<IDrm> drm = GetDrm(env, thiz); + + if (!CheckSession(env, drm, jsessionId)) { + return gSecurityLevels.kSecurityLevelUnknown; + } + + Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); + + DrmPlugin::SecurityLevel level = DrmPlugin::kSecurityLevelUnknown; + + status_t err = drm->getSecurityLevel(sessionId, &level); + + if (throwExceptionAsNecessary(env, err, "Failed to get security level")) { + return gSecurityLevels.kSecurityLevelUnknown; + } + + switch(level) { + case DrmPlugin::kSecurityLevelSwSecureCrypto: + return gSecurityLevels.kSecurityLevelSwSecureCrypto; + case DrmPlugin::kSecurityLevelSwSecureDecode: + return gSecurityLevels.kSecurityLevelSwSecureDecode; + case DrmPlugin::kSecurityLevelHwSecureCrypto: + return gSecurityLevels.kSecurityLevelHwSecureCrypto; + case DrmPlugin::kSecurityLevelHwSecureDecode: + return gSecurityLevels.kSecurityLevelHwSecureDecode; + case DrmPlugin::kSecurityLevelHwSecureAll: + return gSecurityLevels.kSecurityLevelHwSecureAll; + default: + return gSecurityLevels.kSecurityLevelUnknown; + } +} + + +static void android_media_MediaDrm_setSecurityLevel(JNIEnv *env, + jobject thiz, jbyteArray jsessionId, jint jlevel) { + sp<IDrm> drm = GetDrm(env, thiz); + + if (!CheckSession(env, drm, jsessionId)) { + return; + } + + Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId)); + DrmPlugin::SecurityLevel level; + + if (jlevel == gSecurityLevels.kSecurityLevelSwSecureCrypto) { + level = DrmPlugin::kSecurityLevelSwSecureCrypto; + } else if (jlevel == gSecurityLevels.kSecurityLevelSwSecureDecode) { + level = DrmPlugin::kSecurityLevelSwSecureDecode; + } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureCrypto) { + level = DrmPlugin::kSecurityLevelHwSecureCrypto; + } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureDecode) { + level = DrmPlugin::kSecurityLevelHwSecureDecode; + } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureAll) { + level = DrmPlugin::kSecurityLevelHwSecureAll; + } else { + jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid security level"); + return; + } + + status_t err = drm->setSecurityLevel(sessionId, level); + + if (throwExceptionAsNecessary(env, err, "Failed to set security level")) { + return; + } +} + + static jstring android_media_MediaDrm_getPropertyString( JNIEnv *env, jobject thiz, jstring jname) { sp<IDrm> drm = GetDrm(env, thiz); - if (drm == NULL) { - jniThrowException(env, "java/lang/IllegalStateException", - "MediaDrm obj is null"); + if (!CheckDrm(env, drm)) { return NULL; } @@ -1159,9 +1357,7 @@ static jbyteArray android_media_MediaDrm_getPropertyByteArray( JNIEnv *env, jobject thiz, jstring jname) { sp<IDrm> drm = GetDrm(env, thiz); - if (drm == NULL) { - jniThrowException(env, "java/lang/IllegalStateException", - "MediaDrm obj is null"); + if (!CheckDrm(env, drm)) { return NULL; } @@ -1187,9 +1383,7 @@ static void android_media_MediaDrm_setPropertyString( JNIEnv *env, jobject thiz, jstring jname, jstring jvalue) { sp<IDrm> drm = GetDrm(env, thiz); - if (drm == NULL) { - jniThrowException(env, "java/lang/IllegalStateException", - "MediaDrm obj is null"); + if (!CheckDrm(env, drm)) { return; } @@ -1217,9 +1411,7 @@ static void android_media_MediaDrm_setPropertyByteArray( JNIEnv *env, jobject thiz, jstring jname, jbyteArray jvalue) { sp<IDrm> drm = GetDrm(env, thiz); - if (drm == NULL) { - jniThrowException(env, "java/lang/IllegalStateException", - "MediaDrm obj is null"); + if (!CheckDrm(env, drm)) { return; } @@ -1445,15 +1637,13 @@ static jbyteArray android_media_MediaDrm_signRSANative( static const JNINativeMethod gMethods[] = { - { "release", "()V", (void *)android_media_MediaDrm_release }, + { "native_release", "()V", (void *)android_media_MediaDrm_native_release }, + { "native_init", "()V", (void *)android_media_MediaDrm_native_init }, { "native_setup", "(Ljava/lang/Object;[BLjava/lang/String;)V", (void *)android_media_MediaDrm_native_setup }, - { "native_finalize", "()V", - (void *)android_media_MediaDrm_native_finalize }, - { "isCryptoSchemeSupportedNative", "([BLjava/lang/String;)Z", (void *)android_media_MediaDrm_isCryptoSchemeSupportedNative }, @@ -1497,6 +1687,24 @@ static const JNINativeMethod gMethods[] = { { "releaseAllSecureStops", "()V", (void *)android_media_MediaDrm_releaseAllSecureStops }, + { "getConnectedHdcpLevel", "()I", + (void *)android_media_MediaDrm_getConnectedHdcpLevel }, + + { "getMaxHdcpLevel", "()I", + (void *)android_media_MediaDrm_getMaxHdcpLevel }, + + { "getOpenSessionCount", "()I", + (void *)android_media_MediaDrm_getOpenSessionCount }, + + { "getMaxSessionCount", "()I", + (void *)android_media_MediaDrm_getMaxSessionCount }, + + { "getSecurityLevel", "([B)I", + (void *)android_media_MediaDrm_getSecurityLevel }, + + { "setSecurityLevel", "([BI)V", + (void *)android_media_MediaDrm_setSecurityLevel }, + { "getPropertyString", "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_media_MediaDrm_getPropertyString }, diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml index ff81fc17698c..93c0e1007aa6 100644 --- a/packages/SettingsLib/res/values-af/strings.xml +++ b/packages/SettingsLib/res/values-af/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Inligtingruiling"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Draadlose skermsertifisering"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Aktiveer Wi-Fi-woordryke aanmelding"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aggressiewe Wi‑Fi-na-mobiel-oorhandiging"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Laat altyd Wi-Fi-swerfskanderings toe"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiele data is altyd aktief"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardewareversnelling vir verbinding"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Voer gasheernaam van DNS-verskaffer in"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Wys opsies vir draadlose skermsertifisering"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Verhoog Wi-Fi-aantekeningvlak, wys per SSID RSSI in Wi‑Fi-kieser"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Wanneer dit geaktiveer is, sal Wi-Fi die dataverbinding aggressiewer na mobiel oordra wanneer die Wi-Fi-sein swak is"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Laat toe of verbied Wi-Fi-swerfskanderings op grond van die hoeveelheid dataverkeer wat op die koppelvlak teenwoordig is"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Loggerbuffer se groottes"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Kies loggergroottes per logbuffer"</string> diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml index 111b7cf9eaf3..83fd2afc4787 100644 --- a/packages/SettingsLib/res/values-am/strings.xml +++ b/packages/SettingsLib/res/values-am/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"አውታረ መረብ"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"የገመድ አልባ ማሳያ እውቅና ማረጋገጫ"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"የWi‑Fi ተጨማሪ ቃላት ምዝግብ ማስታወሻ መያዝ"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"አስገዳጅ ከWi‑Fi ወደ ሞባይል ማቀበል"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ሁልጊዜ የWi‑Fi ማንቀሳቀስ ቅኝቶችን ይፍቀዱ"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"የተንቀሳቃሽ ስልክ ውሂብ ሁልጊዜ ገቢር ነው"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"የሃርድዌር ማቀላጠፊያን በማስተሳሰር ላይ"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"የዲኤንኤስ አቅራቢ አስተናጋጅ ስም ያስገቡ"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"የገመድ አልባ ማሳያ እውቅና ማረጋገጫ አማራጮችን አሳይ"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"የWi‑Fi ምዝግብ ማስታወሻ አያያዝ ደረጃ ጨምር፣ በWi‑Fi መምረጫ ውስጥ በአንድ SSID RSSI አሳይ"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"ሲነቃ የWi‑Fi ምልክት ዝቅተኛ ሲሆን Wi‑Fi የውሂብ ግንኙነት ለሞባይል ማስረከብ ላይ ይበልጥ አስገዳጅ ይሆናል"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"በበይነገጹ ላይ ባለው የውሂብ ትራፊክ መጠን ላይ ተመስርተው የWi‑Fi ማንቀሳቀስ ቅኝቶችን ይፍቀዱ/ይከልክሉ"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"የምዝግብ ማስታወሻ ያዥ መጠኖች"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"በአንድ ምዝግብ ማስታወሻ ቋጥ የሚኖረው የምዝግብ ማስታወሻ ያዥ መጠኖች ይምረጡ"</string> diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml index b101a1d2bea2..a541cbd62317 100644 --- a/packages/SettingsLib/res/values-ar/strings.xml +++ b/packages/SettingsLib/res/values-ar/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"الشبكات"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"شهادة عرض شاشة لاسلكي"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"تمكين تسجيل Wi‑Fi Verbose"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"تسليم Wi-Fi حاد إلى جوّال"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"السماح دائمًا بعمليات فحص Wi-Fi للتجوال"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"بيانات الجوّال نشطة دائمًا"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"تسريع الأجهزة للتوصيل"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"أدخل اسم مضيف مزوّد نظام أسماء النطاقات"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"عرض خيارات شهادة عرض شاشة لاسلكي"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"زيادة مستوى تسجيل Wi-Fi، وعرض لكل SSID RSSI في منتقي Wi-Fi"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"عند تمكينه، سيكون Wi-Fi أكثر حدة في تسليم اتصال البيانات إلى الجوّال، وذلك عندما تكون إشارة WiFi منخفضة"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"السماح/عدم السماح بعمليات فحص Wi-Fi للتجوال بناءً على حجم حركة البيانات في الواجهة"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"أحجام ذاكرة التخزين المؤقت للتسجيل"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"حدد أحجامًا أكبر لكل ذاكرة تخزين مؤقت للتسجيل"</string> diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml index 03c9b9225a5c..5b4e45ced376 100644 --- a/packages/SettingsLib/res/values-az/strings.xml +++ b/packages/SettingsLib/res/values-az/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Şəbəkələşmə"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Simsiz displey sertifikatlaşması"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi Çoxsözlü Girişə icazə verin"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Möbül ötürücüyə aqressiv Wi‑Fi"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi axtarışlarına həmişə icazə verin"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobil data həmişə aktiv"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Birləşmə üçün avadanlıq akselerasiyası"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS provayderinin host adını daxil edin"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Simsiz displey sertifikatlaşması üçün seçimləri göstərir"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi giriş səviyyəsini qaldırın, Wi‑Fi seçəndə hər SSID RSSI üzrə göstərin"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Aktiv edildikdə, Wi-Fi siqnalı zəif olan zaman, data bağlantısını mobilə ötürərəkən Wi-Fi daha aqressiv olacaq"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Wi‑Fi Axtarışlarına data trafikinə əsasən İcazə verin/Qadağan edin"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Logger bufer ölçüləri"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Hər jurnal buferinı Logger ölçüsü seçin"</string> diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml index 62e4b4c6b08a..0545021b159d 100644 --- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml +++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Umrežavanje"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Sertifikacija bežičnog ekrana"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Omogući detaljniju evidenciju za Wi‑Fi"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agresivan prelaz sa Wi‑Fi mreže na mobilnu"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Uvek dozvoli skeniranje Wi‑Fi-ja u romingu"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilni podaci su uvek aktivni"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardversko ubrzanje privezivanja"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Unesite ime hosta dobavljača usluge DNS-a"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Prikaz opcija za sertifikaciju bežičnog ekrana"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povećava nivo evidentiranja za Wi‑Fi. Prikaz po SSID RSSI-u u biraču Wi‑Fi mreže"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Kad se omogući, Wi‑Fi će biti agresivniji pri prebacivanju mreže za prenos podataka na mobilnu ako je Wi‑Fi signal slab"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Dozvoli/zabrani skeniranje Wi-Fi-ja u romingu na osnovu prisutnog protoka podataka na interfejsu"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Veličine bafera podataka u programu za evidentiranje"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Izaberite veličine po baferu evidencije"</string> diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml index c648ea5ace03..05be22280f81 100644 --- a/packages/SettingsLib/res/values-be/strings.xml +++ b/packages/SettingsLib/res/values-be/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Сеткі"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Сертыфікацыя бесправаднога дысплея"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Уключыць падрабязны журнал Wi‑Fi"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Інтэнсіўны пераход з Wi‑Fi на маб. сетку"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Заўсёды дазваляць роўмінгавае сканіраванне Wi‑Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Мабільная перадача даных заўсёды актыўная"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Апаратнае паскарэнне ў рэжыме мадэма"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Увядзіце імя вузла аператара DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Паказаць опцыі сертыфікацыі бесправаднога дысплея"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Падвыс. узровень дэтал-цыі журнала Wi‑Fi у залежн. ад SSID RSSI у Wi‑Fi Picker"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Калі гэта функцыя ўключана, Wi-Fi будзе больш інтэнсіўна імкнуцца перайсці на падключ. маб. перад. даных пры слабым сігнале Wi‑Fi"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Дазволіць/забараніць роўмінгавае сканіраванне Wi‑Fi ў залежнасці ад аб\'ёму трафіку даных у інтэрфейсе"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Памеры буфера для сродку вядзення журнала"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Выберыце памеры сродку вядзення журнала для буфераў журнала"</string> diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml index 83c1ec0b0ab7..ea67a980590d 100644 --- a/packages/SettingsLib/res/values-bg/strings.xml +++ b/packages/SettingsLib/res/values-bg/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Мрежи"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Безжичен дисплей"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"„Многословно“ регистр. на Wi‑Fi: Актив."</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi-Fi към моб. мрежи: Агресивно предав."</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Сканирането за роуминг на Wi-Fi да е разрешено винаги"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Винаги активни мобилни данни"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Хардуерно ускорение за тетъринга"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Въведете името на хоста на DNS доставчика"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Показване на опциите за сертифициране на безжичния дисплей"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"По-подробно регистр. на Wi‑Fi – данни за RSSI на SSID в инстр. за избор на Wi‑Fi"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"При активиране предаването на връзката за данни от Wi-Fi към мобилната мрежа ще е по-агресивно, когато сигналът за Wi-Fi е слаб"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Разрешаване/забраняване на сканирането за роуминг на Wi-Fi въз основа на посочения в интерфейса обем на трафика на данни"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Размери на регистрац. буфери"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Размер на един рег. буфер: Избор"</string> diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml index baf9e2c91fc4..f30ed2b87791 100644 --- a/packages/SettingsLib/res/values-bn/strings.xml +++ b/packages/SettingsLib/res/values-bn/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"নেটওয়ার্কিং"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"ওয়্যারলেস ডিসপ্লে সার্টিফিকেশন"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"ওয়াই-ফাই ভারবোস লগিং সক্ষম করুন"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"ওয়াই-ফাই থেকে মোবাইলে তৎপর হস্তান্তর"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"সর্বদা ওয়াই ফাই রোম স্ক্যানকে অনুমতি দিন"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"মোবাইল ডেটা সব সময় সক্রিয় থাক"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"টিথারিং হার্ডওয়্যার অ্যাক্সিলারেশন"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"ডিএনএস প্রদানকারীর হোস্টনেম লিখুন"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ওয়্যারলেস প্রদর্শন সার্টিফিকেশন জন্য বিকল্পগুলি দেখান"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"ওয়াই-ফাই লগিং স্তর বাড়ান, ওয়াই-ফাই চয়নকারীতে SSID RSSI অনুযায়ী দেখান"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"সক্ষম করা থাকলে, ওয়াই ফাই সিগন্যালের মান খারাপ হলে ডেটা সংযোগ মোবাইলের কাছে হস্তান্তর করার জন্য ওয়াই ফাই আরো বেশি তৎপর হবে।"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ইন্টারফেসে উপস্থিত ডেটা ট্রাফিকের পরিমাণের উপরে ভিত্তি করে ওয়াই-ফাই রোম স্ক্যানকে অনুমোদিত/অননুমোদিত করুন"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"লগার বাফারের আকারগুলি"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"লগ বাফার প্রতি অপেক্ষাকৃত বড় আকারগুলির বেছে নিন"</string> diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml index 88b01e9877a9..915eb4917bd1 100644 --- a/packages/SettingsLib/res/values-bs/strings.xml +++ b/packages/SettingsLib/res/values-bs/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Umrežavanje"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Certifikacija bežičnog prikaza"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Omogućiti Wi-Fi Verbose zapisivanje"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agresivni prijenos s Wi-Fi mreže na mob."</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Uvijek dopustiti Wi-Fi lutajuće skeniranje"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilna mreža za prijenos podataka je uvijek aktivna"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardversko ubrzavanje dijeljenja veze"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Unesite naziv host računara pružaoca DNS-a"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Pokaži opcije za certifikaciju Bežičnog prikaza"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povećajte nivo Wi-Fi zapisivanja, pokazati po SSID RSSI Wi-Fi Picker"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Kada je omogućeno, Wi-Fi veza će u slučaju slabog signala agresivnije predavati vezu za prijenos podataka na mobilnu vezu"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Dozvoli/Zabrani Wi-Fi lutajuće skeniranje na osnovu količine podatkovnog saobraćaja prisutnog na interfejsu"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Veličine bafera za zapisnik"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Odaberite veličine za Logger prema međumemoriji evidencije"</string> diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml index 48223ce614ba..d8c66933310e 100644 --- a/packages/SettingsLib/res/values-ca/strings.xml +++ b/packages/SettingsLib/res/values-ca/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Xarxes"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Certificació de pantalla sense fil"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Activa el registre Wi‑Fi detallat"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Transferència agressiva de Wi-Fi a mòbil"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permet sempre cerca de Wi-Fi en ininerància"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Dades mòbils sempre actives"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Acceleració per maquinari per compartir la xarxa"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introdueix el nom d\'amfitrió del proveïdor de DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostra les opcions de certificació de pantalla sense fil"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Augmenta nivell de registre Wi‑Fi i mostra\'l per SSID RSSI al Selector de Wi‑Fi"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Quan s\'activa, la Wi-Fi és més agressiva en transferir la connexió de dades al mòbil quan el senyal de la Wi-Fi sigui dèbil"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permet/No permetis cerques de xarxes Wi-Fi en itinerància basades en la quantitat de dades presents a la interfície"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Mides memòria intermèdia Logger"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Mida Logger per memòria intermèdia"</string> diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml index 88bbaa77399f..41ff8e23f83c 100644 --- a/packages/SettingsLib/res/values-cs/strings.xml +++ b/packages/SettingsLib/res/values-cs/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Sítě"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Certifikace bezdrát. displeje"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Podrobné protokolování Wi‑Fi"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agresivní předání z Wi-Fi na mobilní síť"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vždy povolit Wi-Fi roaming"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilní data jsou vždy aktivní"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardwarová akcelerace tetheringu"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Zadejte název hostitele poskytovatele DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Zobrazit možnosti certifikace bezdrátového displeje"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Zvýšit úroveň protokolování Wi‑Fi zobrazenou v SSID a RSSI při výběru sítě Wi‑Fi."</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Pokud je tato možnost zapnuta, bude síť Wi-Fi při předávání datového připojení mobilní síti při slabém signálu Wi-Fi agresivnější."</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Povolí nebo zakáže Wi-Fi roaming na základě množství datového provozu na rozhraní."</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Vyrovnávací paměť protokol. nástroje"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Velikost vyrovnávací paměti protokol. nástroje"</string> @@ -395,7 +393,7 @@ <string name="content_description_menu_button" msgid="8182594799812351266">"Nabídka"</string> <string name="retail_demo_reset_message" msgid="118771671364131297">"Chcete-li v ukázkovém režimu obnovit zařízení do továrního nastavení, zadejte heslo"</string> <string name="retail_demo_reset_next" msgid="8356731459226304963">"Další"</string> - <string name="retail_demo_reset_title" msgid="696589204029930100">"Je třeba zadat heslo"</string> + <string name="retail_demo_reset_title" msgid="696589204029930100">"Zadejte heslo"</string> <string name="active_input_method_subtypes" msgid="3596398805424733238">"Aktivní metody zadávání"</string> <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Použít systémové jazyky"</string> <string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Nastavení aplikace <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> se nepodařilo otevřít"</string> diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml index 6f36bc563e3a..17d1f083ecb3 100644 --- a/packages/SettingsLib/res/values-da/strings.xml +++ b/packages/SettingsLib/res/values-da/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Netværk"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Certificering af trådløs skærm"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Aktivér detaljeret Wi-Fi-logføring"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Tvungen skift fra Wi-Fi til mobildata"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Tillad altid scanning af Wi-Fi-roaming"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobildata er altid aktiveret"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardwareacceleration ved netdeling"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Angiv hostname for DNS-udbyder"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Vis valgmuligheder for certificering af trådløs skærm"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Øg mængden af Wi‑Fi-logføring. Vis opdelt efter SSID RSSI i Wi‑Fi-vælgeren"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Når dette er aktiveret, gennemtvinges en overdragelse af dataforbindelsen fra Wi-Fi til mobilnetværk, når Wi-Fi-signalet er svagt"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Tillad/forbyd scanning i forbindelse med Wi-Fi-roaming afhængigt af mængden af datatrafik i grænsefladen"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Størrelser for Logger-buffer"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Vælg Logger-størrelser pr. logbuffer"</string> diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml index 4d53e2dd07bb..2fbac9315979 100644 --- a/packages/SettingsLib/res/values-de/strings.xml +++ b/packages/SettingsLib/res/values-de/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Netzwerke"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Kabellose Übertragung"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Ausführliche WLAN-Protokolle aktivieren"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aggressives Handover von WLAN an Mobilfunk"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"WLAN-Roamingsuchen immer zulassen"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile Datennutzung immer aktiviert"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardwarebeschleunigung für Tethering"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Hostname des DNS-Anbieters eingeben"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Optionen zur Zertifizierung für kabellose Übertragung anzeigen"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Level für WLAN-Protokollierung erhöhen, in WiFi Picker pro SSID-RSSI anzeigen"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Wenn diese Option aktiviert ist, ist das WLAN bei schwachem Signal bei der Übergabe der Datenverbindung an den Mobilfunk aggressiver"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"WLAN-Roamingsuchen je nach Umfang des Datentraffics an der Schnittstelle zulassen bzw. nicht zulassen"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Logger-Puffergrößen"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Größe pro Protokollpuffer wählen"</string> diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml index e5103564d0cc..25de91426de7 100644 --- a/packages/SettingsLib/res/values-el/strings.xml +++ b/packages/SettingsLib/res/values-el/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Δικτύωση"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Πιστοποίηση ασύρματης οθόνης"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Ενεργοποίηση λεπτομερ. καταγραφής Wi-Fi"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Επιθ.μεταβ. Wi-Fi σε δίκτυο κιν.τηλ."</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Να επιτρέπεται πάντα η σάρωση Wi-Fi κατά την περιαγωγή"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Πάντα ενεργά δεδομένα κινητής τηλεφωνίας"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Σύνδεση επιτάχυνσης υλικού"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Εισαγάγετε το όνομα κεντρικού υπολογιστή του παρόχου DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Εμφάνιση επιλογών για πιστοποίηση ασύρματης οθόνης"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Αύξηση επιπέδου καταγ. Wi-Fi, εμφάνιση ανά SSID RSSI στο εργαλείο επιλογής Wi-Fi"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Όταν είναι ενεργό, το Wi-Fi θα μεταβιβάζει πιο επιθετικά τη σύνδ.δεδομένων σε δίκτυο κινητής τηλ., όταν το σήμα Wi-Fi είναι χαμηλό"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Να επιτρέπεται/να μην επιτρέπεται η σάρωση Wi-Fi κατά την περιαγωγή, βάσει της ποσότητας επισκεψιμότητας δεδομένων στη διεπαφή"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Μέγεθος προσωρινής μνήμης για τη λειτουργία καταγραφής"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Μέγεθος αρχείων κατ/φής ανά προ/νή μνήμη αρχείου κατ/φής"</string> diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml index a32238898bc7..9f5353f4b1cd 100644 --- a/packages/SettingsLib/res/values-en-rAU/strings.xml +++ b/packages/SettingsLib/res/values-en-rAU/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Networking"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Wireless display certification"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Enable Wi‑Fi verbose logging"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aggressive Wi‑Fi to mobile handover"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile data always active"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Enter hostname of DNS provider"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Show options for wireless display certification"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Increase Wi‑Fi logging level, show per SSID RSSI in Wi‑Fi Picker"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"When enabled, Wi‑Fi will be more aggressive in handing over the data connection to mobile, when Wi‑Fi signal is low"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Allow/Disallow Wi‑Fi Roam Scans based on the amount of data traffic present at the interface"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Logger buffer sizes"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Select Logger sizes per log buffer"</string> diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml index a32238898bc7..9f5353f4b1cd 100644 --- a/packages/SettingsLib/res/values-en-rCA/strings.xml +++ b/packages/SettingsLib/res/values-en-rCA/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Networking"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Wireless display certification"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Enable Wi‑Fi verbose logging"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aggressive Wi‑Fi to mobile handover"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile data always active"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Enter hostname of DNS provider"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Show options for wireless display certification"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Increase Wi‑Fi logging level, show per SSID RSSI in Wi‑Fi Picker"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"When enabled, Wi‑Fi will be more aggressive in handing over the data connection to mobile, when Wi‑Fi signal is low"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Allow/Disallow Wi‑Fi Roam Scans based on the amount of data traffic present at the interface"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Logger buffer sizes"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Select Logger sizes per log buffer"</string> diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml index a32238898bc7..9f5353f4b1cd 100644 --- a/packages/SettingsLib/res/values-en-rGB/strings.xml +++ b/packages/SettingsLib/res/values-en-rGB/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Networking"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Wireless display certification"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Enable Wi‑Fi verbose logging"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aggressive Wi‑Fi to mobile handover"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile data always active"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Enter hostname of DNS provider"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Show options for wireless display certification"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Increase Wi‑Fi logging level, show per SSID RSSI in Wi‑Fi Picker"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"When enabled, Wi‑Fi will be more aggressive in handing over the data connection to mobile, when Wi‑Fi signal is low"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Allow/Disallow Wi‑Fi Roam Scans based on the amount of data traffic present at the interface"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Logger buffer sizes"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Select Logger sizes per log buffer"</string> diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml index a32238898bc7..9f5353f4b1cd 100644 --- a/packages/SettingsLib/res/values-en-rIN/strings.xml +++ b/packages/SettingsLib/res/values-en-rIN/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Networking"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Wireless display certification"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Enable Wi‑Fi verbose logging"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aggressive Wi‑Fi to mobile handover"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile data always active"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Enter hostname of DNS provider"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Show options for wireless display certification"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Increase Wi‑Fi logging level, show per SSID RSSI in Wi‑Fi Picker"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"When enabled, Wi‑Fi will be more aggressive in handing over the data connection to mobile, when Wi‑Fi signal is low"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Allow/Disallow Wi‑Fi Roam Scans based on the amount of data traffic present at the interface"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Logger buffer sizes"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Select Logger sizes per log buffer"</string> diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml index 80c2eb8b3eb1..a8561fab9f47 100644 --- a/packages/SettingsLib/res/values-en-rXC/strings.xml +++ b/packages/SettingsLib/res/values-en-rXC/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Networking"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Wireless display certification"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Enable Wi‑Fi Verbose Logging"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aggressive Wi‑Fi to mobile handover"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile data always active"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Enter hostname of DNS provider"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Show options for wireless display certification"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Increase Wi‑Fi logging level, show per SSID RSSI in Wi‑Fi Picker"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"When enabled, Wi‑Fi will be more aggressive in handing over the data connection to mobile, when Wi‑Fi signal is low"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Allow/Disallow Wi‑Fi Roam Scans based on the amount of data traffic present at the interface"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Logger buffer sizes"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Select Logger sizes per log buffer"</string> diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml index 65000b375d8f..eeaf18fdac07 100644 --- a/packages/SettingsLib/res/values-es-rUS/strings.xml +++ b/packages/SettingsLib/res/values-es-rUS/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Redes"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Certificación de pantalla inalámbrica"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Habilitar registro detallado de Wi-Fi"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Priorizar cambio de red Wi-Fi a móvil"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir siempre búsquedas de Wi-Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Datos móviles siempre activados"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleración de hardware de conexión mediante dispositivo portátil"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Ingresa el nombre de host del proveedor de DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opciones de certificación de pantalla inalámbrica"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar nivel de registro Wi-Fi; mostrar por SSID RSSI en el selector de Wi-Fi"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Si habilitas esta opción, se priorizará el cambio de Wi-Fi a datos móviles cuando la señal de Wi-Fi sea débil"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permitir/no permitir las búsquedas de Wi-Fi basadas la cantidad de tráfico de datos presente en la interfaz"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Tamaños de búfer de Logger"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Selecciona el tamaño del Logger por búfer"</string> diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml index 2a5e41b536b0..97d9a1020967 100644 --- a/packages/SettingsLib/res/values-es/strings.xml +++ b/packages/SettingsLib/res/values-es/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Redes"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Certificación de pantalla inalámbrica"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Habilitar registro Wi-Fi detallado"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Transferencia agresiva de Wi-Fi a móvil"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir siempre búsquedas de Wi-Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Datos móviles siempre activos"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleración por hardware para conexión compartida"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introduce el nombre de host del proveedor de DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opciones para la certificación de la pantalla inalámbrica"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar el nivel de registro de Wi-Fi, mostrar por SSID RSSI en el selector Wi-Fi"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Si se activa esta opción, la conexión Wi-Fi será más agresiva al pasar la conexión a datos móviles (si la señal Wi-Fi es débil)"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permitir/No permitir búsquedas de Wi-Fi basadas en la cantidad de tráfico de datos presente en la interfaz"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Tamaños de búfer de registrador"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Elige el tamaño del Logger por búfer"</string> diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml index a8ac99f896ff..b680b843919a 100644 --- a/packages/SettingsLib/res/values-et/strings.xml +++ b/packages/SettingsLib/res/values-et/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Võrgustik"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Juhtmeta ekraaniühenduse sertifitseerimine"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Luba WiFi paljusõnaline logimine"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agress. üleminek WiFi-lt mobiilsidele"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Luba alati WiFi-rändluse skannimine"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiilne andmeside on alati aktiivne"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Jagamise riistvaraline kiirendus"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Sisestage DNS-i teenusepakkuja hostinimi"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Juhtmeta ekraaniühenduse sertifitseerimisvalikute kuvamine"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Suurenda WiFi logimistaset, kuva WiFi valijas SSID RSSI järgi"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Kui seade on lubatud, asendatakse nõrga signaaliga WiFi-ühendus agressiivsemalt mobiilse andmesideühendusega"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Luba/keela WiFi-rändluse skannimine liidese andmeliikluse põhjal"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Logija puhvri suurused"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Vali logija suur. logipuhvri kohta"</string> diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml index 2c81f2ef5ace..ca8ea039919e 100644 --- a/packages/SettingsLib/res/values-eu/strings.xml +++ b/packages/SettingsLib/res/values-eu/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Sareak"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Hari gabeko bistaratze-egiaztatzea"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Gaitu Wi-Fi sareetan saioa hasteko modu xehatua"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Behartu Wi-Fi konexiotik datuenera aldatzera"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Onartu beti ibiltaritzan Wi-Fi sareak bilatzea"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Datu mugikorrak beti aktibo"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Konexioa partekatzeko hardwarearen azelerazioa"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Idatzi DNS hornitzailearen ostalari-izena"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Erakutsi hari gabeko bistaratze-egiaztapenaren aukerak"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Erakutsi datu gehiago Wi-Fi sareetan saioa hasterakoan. Erakutsi sarearen identifikatzailea eta seinalearen indarra Wi‑Fi sareen hautagailuan."</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Aukera hori gaituz gero, gailua nahitaez aldatuko da datu mugikorren konexiora Wi-Fi seinalea ahultzen dela nabaritutakoan"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Onartu edo debekatu ibiltaritzan Wi-Fi sareak bilatzea, interfazeko datu-trafikoaren arabera"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Erregistroen buffer-tamainak"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Hautatu erregistroen buffer-tamainak"</string> diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml index 4f3c77f7e9da..675e3827731b 100644 --- a/packages/SettingsLib/res/values-fa/strings.xml +++ b/packages/SettingsLib/res/values-fa/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"شبکه"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"گواهینامه نمایش بیسیم"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"فعال کردن گزارشگیری طولانی Wi‑Fi"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi‑Fi قوی برای واگذاری به دستگاه همراه"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"اسکنهای رومینگ Wi‑Fi همیشه مجاز است"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"داده تلفن همراه همیشه فعال باشد"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"شتاب سختافزاری اتصال به اینترنت با تلفن همراه"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"نام میزبان ارائهدهنده DNS خصوصی را وارد کنید"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"نمایش گزینهها برای گواهینامه نمایش بیسیم"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"افزایش سطح گزارشگیری Wi‑Fi، نمایش به ازای SSID RSSI در انتخابکننده Wi‑Fi"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"زمانیکه فعال است، درشرایطی که سیگنال Wi-Fi ضعیف باشد، Wi‑Fi برای واگذاری اتصال داده به دستگاه همراه قویتر عمل خواهد کرد."</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"مجاز/غیرمجاز کردن اسکنهای رومینگ Wi‑Fi براساس مقدار ترافیک داده موجود در واسط"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"اندازههای حافظه موقت ثبتکننده"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"انتخاب اندازه ثبتکننده در حافظه موقت ثبت"</string> diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml index 5932d00afb0f..ba7fcd39ca3a 100644 --- a/packages/SettingsLib/res/values-fi/strings.xml +++ b/packages/SettingsLib/res/values-fi/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Yhteysominaisuudet"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Langattoman näytön sertifiointi"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Käytä Wi-Fin laajennettua lokikirjausta"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Vaihda herkästi Wi-Fi mobiiliyhteyteen"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Salli Wi-Fi-verkkovierailuskannaus aina"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiilidata aina käytössä"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Laitteistokiihdytyksen yhteyden jakaminen"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Anna isäntänimi tai DNS-tarjoaja."</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Näytä langattoman näytön sertifiointiin liittyvät asetukset"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Lisää Wi‑Fin lokikirjaustasoa, näytä SSID RSSI -kohtaisesti Wi‑Fi-valitsimessa."</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Kun asetus on käytössä, datayhteys siirtyy helpommin Wi-Fistä matkapuhelinverkkoon, jos Wi-Fi-signaali on heikko."</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Salli/estä Wi-Fi-verkkovierailuskannaus liittymässä esiintyvän dataliikenteen perusteella."</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Lokipuskurien koot"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Valitse puskurikohtaiset lokikoot"</string> diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml index c0c29d3236fd..f266e2ddb725 100644 --- a/packages/SettingsLib/res/values-fr-rCA/strings.xml +++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Réseautage"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Certification de l\'affichage sans fil"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Autoriser enreg. données Wi-Fi détaillées"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Passage forcé du Wi-Fi aux données cell."</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Toujours autoriser la détection de réseaux Wi-Fi en itinérance"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Données cellulaires toujours actives"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Accélération matérielle pour le partage de connexion"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Entrez le nom d\'hôte du fournisseur DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Afficher les options pour la certification d\'affichage sans fil"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Détailler davantage les données Wi-Fi, afficher par SSID RSSI dans sélect. Wi-Fi"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Si cette option est activée, le passage du Wi-Fi aux données cellulaires est forcé lorsque le signal Wi-Fi est faible"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Autoriser ou non la détection de réseaux Wi-Fi en itinérance en fonction de l\'importance du transfert de données dans l\'interface"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Tailles des mémoires tampons d\'enregistreur"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Tailles enreg. par tampon journal"</string> diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml index 50c99e2a558e..87f00d151e18 100644 --- a/packages/SettingsLib/res/values-fr/strings.xml +++ b/packages/SettingsLib/res/values-fr/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Mise en réseau"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Certification affichage sans fil"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Autoriser enreg. infos Wi-Fi détaillées"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Passage forcé Wi-Fi vers données mobiles"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Toujours autoriser la détection de réseaux Wi-Fi en itinérance"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Données mobiles toujours actives"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Accélération matérielle pour le partage de connexion"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Saisissez le nom d\'hôte du fournisseur DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Afficher les options de la certification de l\'affichage sans fil"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Détailler plus infos Wi-Fi, afficher par RSSI de SSID dans outil sélection Wi-Fi"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Si cette option est activée, le passage du Wi-Fi aux données mobiles est forcé en cas de signal Wi-Fi faible."</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Autoriser ou non la détection de réseaux Wi-Fi en itinérance en fonction de l\'importance du trafic de données dans l\'interface"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Tailles mémoires tampons enregistr."</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Tailles enreg. par tampon journal"</string> diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml index 775bbf1a9bbd..9026aaba9f68 100644 --- a/packages/SettingsLib/res/values-gl/strings.xml +++ b/packages/SettingsLib/res/values-gl/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Redes"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Certificado de visualización sen fíos"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Activar rexistro detallado da wifi"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Transferencia agresiva de wifi a móbil"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir sempre buscas de itinerancia da wifi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Datos móbiles sempre activados"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleración de hardware para conexión compartida"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introduce o nome de host de provedor de DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostra opcións para o certificado de visualización sen fíos"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar o nivel de rexistro da wifi, mostrar por SSID RSSI no selector de wifi"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Cando estea activada esta función, a wifi será máis agresiva ao transferir a conexión de datos ao móbil cando o sinal wifi sexa feble"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permitir/Non permitir buscas de itinerancia da wifi baseadas na cantidade de tráfico de datos presente na interface"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Tamaños de búfer de rexistrador"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Seleccionar tamaños por búfer"</string> diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml index 712e57eb09da..b1ee90b2c6b0 100644 --- a/packages/SettingsLib/res/values-gu/strings.xml +++ b/packages/SettingsLib/res/values-gu/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"નેટવર્કિંગ"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"વાયરલેસ ડિસ્પ્લે પ્રમાણન"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"વાઇ-ફાઇ વર્બોઝ લૉગિંગ સક્ષમ કરો"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"સશક્ત Wi‑Fiથી મોબાઇલ પર હૅન્ડઓવર"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"હંમેશા વાઇ-ફાઇ રોમ સ્કૅન્સને મંજૂરી આપો"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"મોબાઇલ ડેટા હંમેશાં સક્રિય"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"ટિથરિંગ માટે હાર્ડવેર ગતિવૃદ્ધિ"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS પ્રદાતાના હોસ્ટનું નામ દાખલ કરો"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"વાયરલેસ ડિસ્પ્લે પ્રમાણપત્ર માટેના વિકલ્પો બતાવો"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"વાઇ-ફાઇ લોગિંગ સ્તર વધારો, વાઇ-ફાઇ પીકરમાં SSID RSSI દીઠ બતાવો"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"જ્યારે સક્ષમ કરેલ હોય, ત્યારે વાઇ-ફાઇ સિગ્નલ નબળું હોવા પર, વાઇ-ફાઇ વધુ ઝડપથી ડેટા કનેક્શનને મોબાઇલ પર મોકલશે"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ઇન્ટરફેસ પર હાજર ડેટા ટ્રાફિકના પ્રમાણનાં આધારે વાઇ-ફાઇ રોમ સ્કૅન્સને મંજૂરી આપો/નામંજૂર કરો"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"લોગર બફર કદ"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"લૉગ દીઠ લૉગર કદ બફર પસંદ કરો"</string> diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml index a88abb5a7fa8..e235fc5b7741 100644 --- a/packages/SettingsLib/res/values-hi/strings.xml +++ b/packages/SettingsLib/res/values-hi/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"नेटवर्किंग"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"वायरलेस दिखाई देने के लिए प्रमाणन"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"वाई-फ़ाई वर्बोस लॉगिंग चालू करें"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"वाई-फ़ाई से मोबाइल पर ज़्यादा तेज़ी से हैंडओवर"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"हमेशा वाई-फ़ाई रोम स्कैन करने दें"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"मोबाइल डेटा हमेशा सक्रिय"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"हार्डवेयर से तेज़ी लाने के लिए टेदर करें"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS सेवा देने वाले का होस्टनाम डालें"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"वायरलेस दिखाई देने के लिए प्रमाणन विकल्प दिखाएं"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"वाई-फ़ाई प्रवेश स्तर बढ़ाएं, वाई-फ़ाई पिकर में प्रति SSID RSSI दिखाएं"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"इसके सक्षम होने पर, जब वाई-फ़ाई संकेत कमज़ोर हों तो वाई-फ़ाई, डेटा कनेक्शन को मोबाइल पर ज़्यादा तेज़ी से भेजेगा"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"इंटरफ़ेस पर वर्तमान में मौजूद डेटा ट्रैफ़िक के आधार पर वाई-फ़ाई रोम स्कैन करने देता/नहीं देता है"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"लॉगर बफ़र आकार"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"प्रति लॉग बफ़र लॉगर आकार चुनें"</string> diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml index a417cc153f77..a8549872146f 100644 --- a/packages/SettingsLib/res/values-hr/strings.xml +++ b/packages/SettingsLib/res/values-hr/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Umrežavanje"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Certifikacija bežičnog prikaza"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Omogući opširnu prijavu na Wi-Fi"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aktivni prijelaz s Wi‑Fi na mob. mrežu"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Uvijek dopusti slobodno traženje Wi-Fi mreže"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilni podaci uvijek aktivni"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardversko ubrzanje za modemsko povezivanje"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Unesite naziv hosta davatelja usluge DNS-a"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Prikaži opcije za certifikaciju bežičnog prikaza"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povećana razina prijave na Wi‑Fi, prikaz po SSID RSSI-ju u Biraču Wi‑Fi-ja"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Ako je omogućeno, Wi-Fi će aktivno prebacivati podatkovnu vezu mobilnoj mreži kada je Wi-Fi signal slab."</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Dopustite ili blokirajte slobodno traženje Wi-Fi mreža na temelju količine podatkovnog prometa na sučelju."</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Veličine međuspremnika zapisnika"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Odaberite veličinu međuspremnika zapisnika"</string> diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml index b6f1460a7ba5..553ed88d779e 100644 --- a/packages/SettingsLib/res/values-hu/strings.xml +++ b/packages/SettingsLib/res/values-hu/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Hálózatok"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Vezeték nélküli kijelző tanúsítványa"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Részletes Wi-Fi-naplózás engedélyezése"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agresszív Wi‑Fi–mobilhálózat átadás"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi-roaming ellenőrzésének engedélyezése mindig"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"A mobilhálózati kapcsolat mindig aktív"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Internetmegosztás hardveres gyorsítása"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Adja meg a DNS-szolgáltató gazdagépnevét"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Vezeték nélküli kijelző tanúsítványával kapcsolatos lehetőségek megjelenítése"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi-naplózási szint növelése, RSSI/SSID megjelenítése a Wi‑Fi-választóban"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Ha engedélyezi, a Wi-Fi agresszívebben fogja átadni az adatkapcsolatot a mobilhálózatnak gyenge Wi-Fi-jel esetén"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"A Wi-Fi-roaming ellenőrzésének engedélyezése vagy letiltása az interfészen jelen lévő adatforgalom mennyiségétől függően"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Naplózási puffer mérete"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Naplózási pufferméret kiválasztása"</string> diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml index 3ba3f453a361..dced49f50fa3 100644 --- a/packages/SettingsLib/res/values-hy/strings.xml +++ b/packages/SettingsLib/res/values-hy/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Ցանց"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Անլար էկրանի վկայագրում"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Միացնել Wi‑Fi մանրամասն գրանցամատյանները"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi-Fi-ից կտրուկ անցում բջջային ինտերնետի"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Միշտ թույլատրել Wi‑Fi ռոումինգի որոնումը"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Բջջային ինտերնետը միշտ ակտիվ է"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Սարքակազմի արագացման միացում"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Մուտքագրեք DNS ծառայության մատակարարի խնամորդի անունը"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Ցույց տալ անլար էկրանի հավաստագրման ընտրանքները"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Բարձրացնել մակարդակը, Wi‑Fi ընտրիչում ամեն մի SSID-ի համար ցույց տալ RSSI"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Եթե այս գործառույթը միացված է, Wi-Fi-ի թույլ ազդանշանի դեպքում Wi‑Fi ինտերնետից բջջային ինտերնետի անցումը ավելի կտրուկ կկատարվի"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Թույլատրել/արգելել Wi‑Fi ռոումինգի որոնումը՝ կախված միջերեսում տվյալների երթևեկի ծավալից"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Տեղեկամատյանի պահնակի չափերը"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Ընտրեք տեղեկամատյանի չափը մեկ պահնակի համար"</string> diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml index 2bb9ae0f3e1f..5c067663970a 100644 --- a/packages/SettingsLib/res/values-in/strings.xml +++ b/packages/SettingsLib/res/values-in/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Jaringan"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Sertifikasi layar nirkabel"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Aktifkan Pencatatan Log Panjang Wi-Fi"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Pengalihan Wi-Fi Agresif ke seluler"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Selalu izinkan Pemindaian Roaming Wi-Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Data seluler selalu aktif"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Akselerasi hardware tethering"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Masukkan hostname penyedia DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Tampilkan opsi untuk sertifikasi layar nirkabel"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Tingkatkan level pencatatan log Wi-Fi, tampilkan per SSID RSSI di Pemilih Wi‑Fi"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Jika diaktifkan, Wi-Fi akan menjadi lebih agresif dalam mengalihkan sambungan data ke seluler saat sinyal Wi-Fi lemah"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Izinkan/Larang Pemindaian Roaming Wi-Fi berdasarkan jumlah lalu lintas data yang ada di antarmuka"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Ukuran penyangga pencatat log"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Ukuran Pencatat Log per penyangga log"</string> diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml index 311227f35875..21b8b0ed2975 100644 --- a/packages/SettingsLib/res/values-is/strings.xml +++ b/packages/SettingsLib/res/values-is/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Netkerfi"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Vottun þráðlausra skjáa"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Kveikja á ítarlegri skráningu Wi-Fi"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Hröð skipti úr Wi‑Fi í farsímagögn"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Leyfa alltaf reikileit með Wi-Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Alltaf kveikt á farsímagögnum"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Vélbúnaðarhröðun fyrir tjóðrun"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Slá inn hýsilheiti DNS-veitu"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Sýna valkosti fyrir vottun þráðlausra skjáa"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Auka skráningarstig Wi-Fi, sýna RSSI fyrir hvert SSID í Wi-Fi vali"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Þegar þetta er virkt mun Wi-Fi skipta hraðar yfir í farsímagagnatengingu þegar Wi-Fi-tenging er léleg"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Leyfa/banna reikileit með Wi-Fi á grunni þess hversu mikil gagnaumferð er fyrir hendi í viðmótinu"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Annálsritastærðir biðminna"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Veldu annálsritastærðir á biðminni"</string> diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml index b63232d7a6a6..7408b25f7d10 100644 --- a/packages/SettingsLib/res/values-it/strings.xml +++ b/packages/SettingsLib/res/values-it/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Reti"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Certificazione display wireless"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Attiva registrazione dettagliata Wi-Fi"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi‑Fi aggressivo per passaggio a cellulare"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Consenti sempre scansioni roaming Wi-Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Dati mobili sempre attivi"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering accelerazione hardware"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Inserisci il nome host del provider DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostra opzioni per la certificazione display wireless"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumenta il livello di registrazione Wi-Fi, mostrando il SSID RSSI nel selettore Wi-Fi"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Con questa impostazione attivata, il Wi-Fi è più aggressivo nel passare la connessione dati al cellulare, con segnale Wi-Fi basso"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Consenti/vieta scansioni roaming Wi-Fi basate sulla quantità di traffico dati presente a livello di interfaccia"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Dimensioni buffer Logger"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Seleziona dimensioni Logger per buffer log"</string> diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml index 538da919c798..fceaacc0b7b6 100644 --- a/packages/SettingsLib/res/values-iw/strings.xml +++ b/packages/SettingsLib/res/values-iw/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"תקשורת רשתות"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"אישור של תצוגת WiFi"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"הפעל רישום מפורט של Wi‑Fi ביומן"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"העברה אגרסיבית מ-Wi‑Fi לרשת סלולרית"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"התר תמיד סריקות נדידה של Wi‑Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"חבילת הגלישה פעילה תמיד"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"שיפור מהירות באמצעות חומרה לצורך שיתוף אינטרנט בין ניידים"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"צריך להזין את שם המארח של ספק DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"הצג אפשרויות עבור אישור של תצוגת WiFi"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"העלה את רמת הרישום של Wi‑Fi ביומן, הצג לכל SSID RSSI ב-Wi‑Fi Picker"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"כשאפשרות זו מופעלת, Wi-Fi יתנהג בצורה אגרסיבית יותר בעת העברת חיבור הנתונים לרשת הסלולרית כשאות ה-Wi-Fi חלש."</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"התר/מנע סריקות נדידה של Wi-Fi בהתבסס על נפח תנועת הנתונים הקיימת בממשק"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"גדלי מאגר של יומן רישום"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"בחר גדלים של יוצר יומן לכל מאגר יומן"</string> diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml index db1baa1188c0..671320bc9444 100644 --- a/packages/SettingsLib/res/values-ja/strings.xml +++ b/packages/SettingsLib/res/values-ja/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"ネットワーク"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"ワイヤレスディスプレイ認証"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi-Fi詳細ログの有効化"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi-Fi を強制的にモバイル接続に切り替える"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fiローミングスキャンを常に許可する"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"モバイルデータを常に ON にする"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"テザリング時のハードウェア アクセラレーション"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS プロバイダのホスト名を入力"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ワイヤレスディスプレイ認証のオプションを表示"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fiログレベルを上げて、Wi-Fi選択ツールでSSID RSSIごとに表示します"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"ON にすると、Wi-Fi の電波強度が弱い場合は強制的にモバイルデータ接続に切り替わるようになります"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"インターフェースのデータトラフィック量に基づいたWi-Fiローミングスキャンを許可するかしないかを設定できます"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"ログバッファのサイズ"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"各ログバッファのログサイズを選択"</string> diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml index 00eaf84733d4..1948460ff731 100644 --- a/packages/SettingsLib/res/values-ka/strings.xml +++ b/packages/SettingsLib/res/values-ka/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"ქსელი"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"უსადენო ეკრანის სერტიფიცირება"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi-ს დაწვრილებითი აღრიცხვის ჩართვა"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi‑Fi-ს მობ. ინტერნეტზე აგრესიული გადართვა"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi Roam სკანირების მუდამ დაშვება"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"მობილური ინტერნეტის ყოველთვის გააქტიურება"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"ტეტერინგის აპარატურული აჩქარება"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"შეიყვანეთ DNS პროვაიდერის სერვერის სახელი"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"უსადენო ეკრანის სერტიფიცირების ვარიანტების ჩვენება"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi-ს აღრიცხვის დონის გაზრდა, Wi‑Fi ამომრჩეველში ყოველ SSID RSSI-ზე ჩვენება"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"ჩართვის შემთხვევაში, Wi‑Fi უფრო აქტიურად შეეცდება მობილურ ინტერნეტზე გადართვას, როცა Wi‑Fi სიგნალი სუსტია"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Wifi Roam სკანირების დაშვება/აკრძალვა, ინტერფეისზე არსებული მონაცემთა ტრაფიკზე დაფუძნებით"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"ჟურნალიზაციის ბუფერის ზომები"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"აირჩიეთ ჟურნ. ზომა / ჟურნ. ბუფერზე"</string> diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml index a318bd88a8f0..2d03f7f82bc8 100644 --- a/packages/SettingsLib/res/values-kk/strings.xml +++ b/packages/SettingsLib/res/values-kk/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Желі орнату"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Сымсыз дисплей сертификаты"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi егжей-тегжейлі журналға тір. қосу"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi-Fi желісінен мобильдік желіге ауысу"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi роумингін іздеулерге әрқашан рұқсат ету"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Мобильдік деректер әрқашан қосулы"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Тетерингтің аппараттық жеделдетуі"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS провайдерінің хост атауын енгізіңіз"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Сымсыз дисплей растау опцияларын көрсету"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi жур. тір. дең. арт., Wi‑Fi желісін таңдағышта әр SSID RSSI бойынша көрсету"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Wi‑Fi сигналы әлсіз болғанда, деректер байланысы мәжбүрлі түрде мобильдік желіге ауысады"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Интерфейсте бар деректер трафигінің мөлшерінің негізінде Wi-Fi роумингін іздеулерге рұқсат ету/тыйым салу"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Журналға тіркеуші буферінің өлшемдері"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Әр журнал буфері үшін журналға тіркеуші өлшемдерін таңдау"</string> diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml index ae473187219b..1d2476cf6ca8 100644 --- a/packages/SettingsLib/res/values-km/strings.xml +++ b/packages/SettingsLib/res/values-km/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"ការភ្ជាប់បណ្ដាញ"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"បង្ហាញការកំណត់រចនាសម្ព័ន្ធឥតខ្សែ"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"បើកកំណត់ហេតុរៀបរាប់វ៉ាយហ្វាយ"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"ប្តូរទៅប្រើបណ្តាញចល័តពេល Wi‑Fi មានរលកសញ្ញាខ្លាំងពេក"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"តែងតែអនុញ្ញាតការវិភាគរ៉ូមវ៉ាយហ្វាយ"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"ទិន្នន័យទូរសព្ទចល័តដំណើរការជានិច្ច"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"ការបង្កើនល្បឿនផ្នែករឹងសម្រាប់ការភ្ជាប់"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"បញ្ចូលឈ្មោះម៉ាស៊ីនរបស់ក្រុមហ៊ុនផ្ដល់សេវា DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"បង្ហាញជម្រើសសម្រាប់វិញ្ញាបនបត្របង្ហាញឥតខ្សែ"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"បង្កើនកម្រិតកំណត់ហេតុវ៉ាយហ្វាយបង្ហាញក្នុង SSID RSSI ក្នុងកម្មវិធីជ្រើសវ៉ាយហ្វាយ"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"នៅពេលដែលបើក នោះ Wi‑Fi នឹងផ្តល់ការតភ្ជាប់ទិន្នន័យយ៉ាងគំហុកទៅបណ្តាញទូរសព្ទចល័ត នៅពេលរលកសញ្ញា Wi‑Fi ចុះខ្សោយ។"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"អនុញ្ញាត/មិនអនុញ្ញាតការវិភាគរ៉ូមវ៉ាយហ្វាយផ្អែកលើចំនួនការបង្ហាញចរាចរណ៍ទិន្នន័យនៅចំណុចប្រទាក់"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"ទំហំ buffer របស់ Logger"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ជ្រើសទំហំ Logger per log buffer"</string> diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml index fbabb627ce4d..385308aafab3 100644 --- a/packages/SettingsLib/res/values-kn/strings.xml +++ b/packages/SettingsLib/res/values-kn/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"ನೆಟ್ವರ್ಕಿಂಗ್"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"ವೈರ್ಲೆಸ್ ಪ್ರದರ್ಶನ ಪ್ರಮಾಣೀಕರಣ"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi ವೆರ್ಬೋಸ್ ಲಾಗಿಂಗ್ ಸಕ್ರಿಯಗೊಳಿಸಿ"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"ವೈ-ಫೈನಿಂದ ಮೊಬೈಲ್ಗೆ ಆಕ್ರಮಣಕಾರಿ ಹಸ್ತಾಂತರ"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ವೈ-ಫೈ ರೋಮ್ ಸ್ಕ್ಯಾನ್ಗಳನ್ನು ಯಾವಾಗಲೂ ಅನುಮತಿಸಿ"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"ಮೊಬೈಲ್ ಡೇಟಾ ಯಾವಾಗಲೂ ಸಕ್ರಿಯ"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"ಹಾರ್ಡ್ವೇರ್ನ ವೇಗವರ್ಧನೆಯನ್ನು ಟೆಥರಿಂಗ್ ಮಾಡಿ"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ಪೂರೈಕೆದಾರರ ಹೋಸ್ಟ್ಹೆಸರನ್ನು ನಮೂದಿಸಿ"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ವೈರ್ಲೆಸ್ ಪ್ರದರ್ಶನ ಪ್ರಮಾಣೀಕರಣಕ್ಕಾಗಿ ಆಯ್ಕೆಗಳನ್ನು ತೋರಿಸು"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi ಲಾಗಿಂಗ್ ಮಟ್ಟನ್ನು ಹೆಚ್ಚಿಸಿ, Wi‑Fi ಆಯ್ಕೆಯಲ್ಲಿ ಪ್ರತಿಯೊಂದು SSID RSSI ತೋರಿಸಿ"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"ಇದು ಸಕ್ರಿಯಗೊಂಡರೆ, ವೈ-ಫೈ ಸಿಗ್ನಲ್ ದುರ್ಬಲವಾಗಿದ್ದಾಗ, ಮೊಬೈಲ್ಗೆ ಡೇಟಾ ಸಂಪರ್ಕವನ್ನು ಹಸ್ತಾಂತರಿಸುವಲ್ಲಿ ವೈ-ಫೈ ಹೆಚ್ಚು ಆಕ್ರಮಣಕಾರಿಯಾಗಿರುತ್ತದೆ"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ಇಂಟರ್ಫೇಸ್ನಲ್ಲಿ ಲಭ್ಯವಿರುವ ಡೇಟಾ ಟ್ರಾಫಿಕ್ ಆಧಾರದ ಮೇಲೆ Wi‑Fi ರೋಮ್ ಸ್ಕ್ಯಾನ್ಗಳನ್ನು ಅನುಮತಿಸಿ/ನಿರಾಕರಿಸಿ"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"ಲಾಗರ್ ಬಫರ್ ಗಾತ್ರಗಳು"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ಪ್ರತಿ ಲಾಗ್ ಬಫರ್ಗೆ ಲಾಗರ್ ಗಾತ್ರಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string> diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml index 4b7d0a4cd680..e1be8dc01d83 100644 --- a/packages/SettingsLib/res/values-ko/strings.xml +++ b/packages/SettingsLib/res/values-ko/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"네트워크"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"무선 디스플레이 인증서"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi-Fi 상세 로깅 사용"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"적극적인 Wi-Fi-모바일 핸드오버"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi 로밍 스캔 항상 허용"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"항상 모바일 데이터 활성화"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"테더링 하드웨어 가속"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS 제공업체의 호스트 이름 입력"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"무선 디스플레이 인증서 옵션 표시"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi 로깅 수준을 높이고, Wi‑Fi 선택도구에서 SSID RSSI당 값을 표시합니다."</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"사용 설정하면 Wi-Fi 신호가 약할 때 데이터 연결을 Wi-Fi에서 모바일 네트워크로 더욱 적극적으로 핸드오버합니다."</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"인터페이스에 표시되는 데이터 트래픽의 양을 기반으로 Wi-Fi 로밍 스캔을 허용하거나 허용하지 않습니다."</string> <string name="select_logd_size_title" msgid="7433137108348553508">"로거 버퍼 크기"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"로그 버퍼당 로거 크기 선택"</string> diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml index 98ca36a6a2d2..d323df2e8405 100644 --- a/packages/SettingsLib/res/values-ky/strings.xml +++ b/packages/SettingsLib/res/values-ky/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Тармактык байланыштарды кеңейтүү"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Зымсыз дисплейди аныктоо"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi дайын-даректүү протоколун иштетүү"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi‑Fi начар болсо, мобилдик Инт-ке өтсүн"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi-Fi Роуминг Скандоо мүмкүнчүлүгүнө ар дайым уруксат берилсин"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Мобилдик Интернет иштей берсин"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Тетерингдин иштешин тездетүү"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS түйүндүн аталышын киргизиңиз"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Зымсыз дисплейди сертификатто мүмкүнчүлүктөрүн көргөзүү"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fi Кармагычта Wi‑Fi протокол деңгээлин жогорулатуу жана ар бир SSID RSSI үчүн көрсөтүү."</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Иштетилсе, Wi-Fi байланышы үзүл-кесил болуп жатканда, Wi-Fi тармагы туташууну мобилдик Интернетке өжөрлүк менен өткөрүп берет"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Интерфейстеги дайындар трафигинин көлөмүнө жараша Wi-Fi Роуминг скандоо мүмкүнчүлүгүн иштетүү/өчүрүү"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Каттагыч буферлеринин өлчөмдөрү"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Каттоо буфери үчүн Каттагычтын көлөмүн тандаңыз"</string> diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml index 6de2a2e95f75..1e58af1c7cd0 100644 --- a/packages/SettingsLib/res/values-lo/strings.xml +++ b/packages/SettingsLib/res/values-lo/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"ການສ້າງເຄືອຂ່າຍ"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"ສະແດງການຮັບຮອງຂອງລະບົບໄຮ້ສາຍ"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"ເປີດນຳໃຊ້ການເກັບປະຫວັດ Verbose Wi‑Fi"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"ສະຫຼັບເປັນ Wi-Fi ເມື່ອມືຖືສັນຍານອ່ອນ"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ອະນຸຍາດການສະແກນການໂຣມ Wi‑Fi ສະເໝີ"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"ເປີດໃຊ້ອິນເຕີເນັດມືຖືຕະຫຼອດເວລາ"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"ເປີດໃຊ້ການເລັ່ງຄວາມໄວດ້ວຍຮາດແວ"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"ລະບຸຊື່ໂຮສຂອງຜູ້ໃຫ້ບໍລິການ DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ສະແດງໂຕເລືອກສຳລັບການສະແດງການຮັບຮອງລະບົບໄຮ້ສາຍ"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"ເພີ່ມລະດັບການເກັບປະຫວັດ Wi‑Fi, ສະແດງຕໍ່ SSID RSSI ໃນ Wi‑Fi Picker"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"ເມື່ອເປີດໃຊ້ແລ້ວ, Wi-Fi ຈະສົ່ງຜ່ານການເຊື່ອມຕໍ່ຂໍ້ມູນໄປຫາເຄືອຂ່າຍມືຖືເມື່ອສັນຍານ Wi-Fi ອ່ອນ"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ອະນຸຍາດ/ບໍ່ອະນຸຍາດການສະແກນການໂຣມ Wi-Fi ອີງຕາມຈຳນວນຂໍ້ມູນທີ່ເກີດຂຶ້ນໃນລະດັບສ່ວນຕິດຕໍ່"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"ຂະໜາດບັບເຟີໂຕລັອກ"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ເລືອກຂະໜາດລັອກຕໍ່ບັບເຟີ"</string> diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml index 66fa62a89723..a35cd3c7be50 100644 --- a/packages/SettingsLib/res/values-lt/strings.xml +++ b/packages/SettingsLib/res/values-lt/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Tinklai"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Belaidžio rodymo sertifikavimas"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Įgal. „Wi‑Fi“ daugiaž. įraš. į žurnalą"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agres. „Wi‑Fi“ perd. į mob. r. tinklą"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Visada leisti „Wi-Fi“ tarptiklinio ryšio nuskaitymą"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiliojo ryšio duomenys visada suaktyvinti"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Įrenginio kaip modemo naudojimo aparatinės įrangos spartinimas"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Įveskite DNS teikėjo prieglobos serverio pavadinimą"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Rodyti belaidžio rodymo sertifikavimo parinktis"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Padidinti „Wi‑Fi“ įrašymo į žurnalą lygį, rodyti SSID RSSI „Wi-Fi“ rinkiklyje"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Jei ši parinktis įgalinta, „Wi‑Fi“ agresyviau perduos duomenų ryšiu į mobiliojo ryšio tinklą, kai „Wi‑Fi“ signalas silpnas"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Leisti / neleisti „Wi‑Fi“ tarptinklinio ryšio nuskaitymo, atsižvelgiant į sąsajos duomenų srauto kiekį"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Registruotuvo buferio dydžiai"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Pasir. registr. dydž. žurn. bufer."</string> diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml index f32accddfc99..8239d9f62042 100644 --- a/packages/SettingsLib/res/values-lv/strings.xml +++ b/packages/SettingsLib/res/values-lv/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Tīklošana"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Bezvadu attēlošanas sertifikācija"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Iespējot Wi‑Fi detalizēto reģistrēšanu"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agresīva pāreja no Wi‑Fi uz mobilo tīklu"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vienmēr atļaut Wi‑Fi meklēšanu"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Vienmēr aktīvs mobilo datu savienojums"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Paātrināta aparatūras darbība piesaistei"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Ievadiet DNS pakalpojumu sniedzēja saimniekdatora nosaukumu"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Rādīt bezvadu attēlošanas sertifikācijas iespējas"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Palieliniet Wi‑Fi reģistrēšanas līmeni; rādīt katram SSID RSSI Wi‑Fi atlasītājā."</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Ja opcija ir iespējota un Wi‑Fi signāls ir vājš, datu savienojuma pāreja no Wi-Fi uz mobilo tīklu tiks veikta agresīvāk."</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Atļaujiet/neatļaujiet Wi‑Fi meklēšanu, pamatojoties uz saskarnē saņemto datplūsmas apjomu."</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Reģistrētāja buferu lielumi"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Atlasīt reģistrētāja bufera liel."</string> diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml index 3151f5677008..eaa553903a32 100644 --- a/packages/SettingsLib/res/values-mk/strings.xml +++ b/packages/SettingsLib/res/values-mk/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Вмрежување"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Приказ на сертификација на безжична мрежа"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Овозможи преопширно пријавување Wi‑Fi"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Агресивно предавање од Wi‑Fi на мобилен"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Секогаш дозволувај Wi‑Fi скенирање во роаминг"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Мобилниот интернет е секогаш активен"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Хардверско забрзување за врзување"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Внесете име на хост на операторот на DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Покажи ги опциите за безжичен приказ на сертификат"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Зголеми Wi‑Fi ниво на пријавување, прикажи по SSID RSSI во Wi‑Fi бирач"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Кога е овозможено, Wi-Fi ќе биде поагресивна при предавање на интернет-врската на мобилната мрежа при слаб сигнал на Wi-Fi"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Дозволи/Забрани Wi‑Fi скенирање во роаминг според количината на постоечкиот податочен сообраќај на интерфејсот."</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Величини на меѓумеморија на забележувач"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Величина/меѓумеморија на дневник"</string> diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml index 2b86e509fb05..0ddfc793312e 100644 --- a/packages/SettingsLib/res/values-ml/strings.xml +++ b/packages/SettingsLib/res/values-ml/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"നെറ്റ്വര്ക്കിംഗ്"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"വയർലെസ് ഡിസ്പ്ലേ സർട്ടിഫിക്കേഷൻ"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"വൈഫൈ വെർബോസ് ലോഗിംഗ് പ്രവർത്തനക്ഷമമാക്കുക"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"മൊബൈൽ ഹാൻഡ്ഓവറിലേക്ക് വൈഫൈ സക്രിയമാക്കുക"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"എപ്പോഴും വൈഫൈ റോം സ്കാൻ അനുവദിക്കൂ"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"മൊബൈൽ ഡാറ്റ എല്ലായ്പ്പോഴും സജീവം"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"ടെതറിംഗ് ഹാർഡ്വെയർ ത്വരിതപ്പെടുത്തൽ"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ദാതാവിന്റെ ഹോസ്റ്റുനാമം നൽകുക"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"വയർലെസ് ഡിസ്പ്ലേ സർട്ടിഫിക്കേഷനായി ഓപ്ഷനുകൾ ദൃശ്യമാക്കുക"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"വൈഫൈ പിക്കറിൽ ഓരോ SSID RSSI പ്രകാരം കാണിക്കാൻ വൈഫൈ ലോഗിംഗ് നില വർദ്ധിപ്പിക്കുക"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"പ്രവർത്തനക്ഷമമായിരിക്കുമ്പോൾ, വൈഫൈ സിഗ്നൽ കുറവായിരിക്കുന്ന സമയത്ത് മൊബൈലിലേക്ക് ഡാറ്റ കണക്ഷൻ വഴി കൈമാറുന്നതിൽ വൈഫൈ കൂടുതൽ സക്രിയമായിരിക്കും"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ഇന്റർഫേസിലെ ഡാറ്റ ട്രാഫിക്ക് സാന്നിദ്ധ്യത്തിന്റെ കണക്ക് അടിസ്ഥാനമാക്കി വൈഫൈ റോം സ്കാനുകൾ അനുവദിക്കുക/അനുവദിക്കാതിരിക്കുക"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"ലോഗർ ബഫർ വലുപ്പം"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ഓരോ ലോഗ് ബഫറിനും വലുപ്പം തിരഞ്ഞെടുക്കൂ"</string> diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml index 152408aa6213..67c64958fed1 100644 --- a/packages/SettingsLib/res/values-mn/strings.xml +++ b/packages/SettingsLib/res/values-mn/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Сүлжээ"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Утасгүй дэлгэцийн сертификат"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi Verbose лог-г идэвхжүүлэх"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Идэвхтэй Wi‑Fi-с мобайл сүлжээнд"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi Роум сканыг байнга зөвшөөрөх"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Мобайл дата байнга идэвхтэй"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Модем болгох хардвер хурдасгуур"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS-н үйлчилгээ үзүүлэгчийн хостын нэрийг оруулах"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Утасгүй дэлгэцийн сертификатын сонголтыг харуулах"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi лог-н түвшинг нэмэгдүүлэх, Wi‑Fi Сонгогч дээрх SSID-д ногдох RSSI-г харуулах"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Идэвхжүүлсэн үед Wi‑Fi холболт сул байх үед дата холболтыг мобайлд шилжүүлэхэд илүү идэвхтэй байх болно"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Интерфэйс дээрх дата трафикын хэмжээнээс хамааран Wi‑Fi Роум Скан-г зөвшөөрөх/үл зөвшөөрөх"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Логгерын буферын хэмжээ"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Лог буфер бүрт ногдох логгерын хэмжээг сонгоно уу"</string> diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml index 7402d29ee2e9..eeb0a165cf37 100644 --- a/packages/SettingsLib/res/values-mr/strings.xml +++ b/packages/SettingsLib/res/values-mr/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"नेटवर्किंग"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"वायरलेस डिस्प्ले प्रमाणीकरण"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"वाय-फाय व्हर्बोझ लॉगिंग सक्षम करा"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"मोबाइलकडे सोपवण्यासाठी अॅग्रेसिव्ह वाय-फाय"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"वाय-फाय रोम स्कॅनला नेहमी अनुमती द्या"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"मोबाइल डेटा नेहमी सक्रिय"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"टेदरिंग हार्डवेअर प्रवेग"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS पुरवठादाराचे होस्टनाव टाका"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"वायरलेस डिस्प्ले प्रमाणिकरणाचे पर्याय दाखवा"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"वाय-फाय लॉगिंग स्तर वाढवा, वाय-फाय सिलेक्टरमध्ये प्रति SSID RSSI दर्शवा"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"सक्षम केले असताना, वाय-फाय सिग्नल कमी असताना, मोबाइलकडे डेटा कनेक्शन सोपवण्यासाठी वाय-फाय अधिक अॅग्रेसिव्ह असेल."</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"वाय-फाय रोम स्कॅनला इंटरफेसवर उपस्थित असलेल्या रहदारी डेटाच्या प्रमाणावर आधारित अनुमती द्या/अनुमती देऊ नका"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"लॉगर बफर आकार"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"प्रति लॉग बफर लॉगर आकार निवडा"</string> diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml index 51ab84e05de6..a69024c50d05 100644 --- a/packages/SettingsLib/res/values-ms/strings.xml +++ b/packages/SettingsLib/res/values-ms/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Perangkaian"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Pensijilan paparan wayarles"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Dayakan Pengelogan Berjela-jela Wi-Fi"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Penyerahan Wi-Fi ke mudah alih agresif"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Sentiasa benarkan Imbasan Perayauan Wi-Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Data mudah alih sentiasa aktif"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Pecutan perkakasan penambatan"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Masukkan nama hos pembekal DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Tunjukkan pilihan untuk pensijilan paparan wayarles"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Tingkatkan tahap pengelogan Wi-Fi, tunjuk setiap SSID RSSI dalam Pemilih Wi-Fi"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Apabila didayakan, Wi-Fi akan menjadi lebih agresif dalam menyerahkan sambungan data ke mudah alih, apabila isyarat Wi-Fi rendah"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Benarkan/Jangan benarkan Imbasan Perayauan Wi-Fi berdasarkan jumlah trafik data yang ada pada antara muka"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Saiz penimbal pengelog"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Pilih saiz Pengelog bagi setiap penimbal log"</string> diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml index c643c595a6ef..5e78249ca172 100644 --- a/packages/SettingsLib/res/values-my/strings.xml +++ b/packages/SettingsLib/res/values-my/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"ချိတ်ဆက်ဆောင်ရွက်ခြင်း"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"ကြိုးမဲ့ပြသမှု အသိအမှတ်ပြုလက်မှတ်"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi Verbose မှတ်တမ်းတင်ခြင်းအား ဖွင့်မည်"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi‑Fi မှ မိုဘိုင်းသို့ လွှဲပြောင်းရန်"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi ရွမ်းရှာဖွေမှုကို အမြဲတမ်း ခွင့်ပြုမည်"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"မိုဘိုင်းဒေတာကို အမြဲဖွင့်ထားရန်"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"ဖုန်းကို မိုဒမ်အဖြစ်အသုံးပြုမှု စက်ပစ္စည်းဖြင့် အရှိန်မြှင့်တင်ခြင်း"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ဝန်ဆောင်မှုပေးသူ၏ အင်တာနက်လက်ခံဝန်ဆောင်ပေးသူအမည်ကို ထည့်ပါ"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ကြိုးမဲ့ အခင်းအကျင်း အသိအမှတ်ပြုလက်မှတ်အတွက် ရွေးချယ်စရာများပြရန်"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi မှတ်တမ်းတင်ခြင်း နှုန်းအားမြင့်ကာ၊ Wi‑Fi ရွေးရာတွင် SSID RSSI ဖြင့်ပြပါ"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"ဖွင့်ထားပါက Wi‑Fi လွှင့်အား နည်းချိန်တွင် Wi‑Fi မှ မိုဘိုင်းသို့ ဒေတာချိတ်ဆက်မှုကို လွှဲပြောင်းရာ၌ ပိုမိုထိရောက်ပါသည်"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"မျက်နှာပြင်တွင် ဖော်ပြသည့် အချက်လက် အသွားအလာ ပမာဏပေါ်တွင် အခြေခံ၍ WIFI ရွမ်းရှာဖွေမှုအား ဖွင့်/ပိတ်မည်"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"လော့ဂါး ဘာဖား ဆိုက်များ"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"လော့ ဘာဖားတွက် လော့ဂါးဆိုက် ရွေး"</string> diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml index 0cea1a78e503..d45bbc3bbe80 100644 --- a/packages/SettingsLib/res/values-nb/strings.xml +++ b/packages/SettingsLib/res/values-nb/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Nettverk"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Trådløs skjermsertifisering"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Aktiver detaljert Wi-Fi-loggføring"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aggressiv overføring fra Wi-Fi til mobil"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Tillat alltid skanning for Wi-Fi-roaming"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobildata er alltid aktiv"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Maskinvareakselerasjon for internettdeling"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Skriv inn vertsnavnet til DNS-leverandøren"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Vis alternativer for sertifisering av trådløs skjerm"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Øk Wi-Fi-loggenivå – vis per SSID RSSI i Wi-Fi-velgeren"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Hvis dette slås på, overfører Wi-Fi-nettverket datatilkoblingen til mobil mer aggressivt når Wi-Fi-signalet er svakt"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Tillat / ikke tillat skanning for Wi-Fi-roaming basert på mengden datatrafikk til stede i grensesnittet"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Bufferstørrelser for logg"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Velg loggstørrelse per loggbuffer"</string> diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml index d0ec0f5ee01d..d26541ca167e 100644 --- a/packages/SettingsLib/res/values-ne/strings.xml +++ b/packages/SettingsLib/res/values-ne/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"नेटवर्किङ"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"ताररहित प्रदर्शन प्रमाणीकरण"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi-Fi वर्बोज लग सक्षम पार्नुहोस्"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"आक्रामक ढंगले Wi‑Fi बाट मोबाइलमा हस्तान्तरण"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi-Fi घुम्ने स्क्यान गर्न सधैँ अनुमति दिनुहोस्"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"मोबाइल डेटा सधैँ सक्रिय राख्नुहोस्"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"टेदरिङको लागि हार्डवेयरको प्रवेग"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS प्रदायकको होस्टनाम प्रविष्ट गर्नुहोस्"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ताररहित प्रदर्शन प्रमाणीकरणका लागि विकल्पहरू देखाउनुहोस्"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fi लग स्तर बढाउनुहोस्, Wi-Fi चयनकर्तामा प्रति SSID RSSI देखाइन्छ"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"सक्षम गरिएको अवस्थामा, Wi-Fi सिग्नल न्यून हुँदा, Wi-Fi ले बढी आक्रामक ढंगले मोबाइलमा डेटा जडान हस्तान्तरण गर्नेछ"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Wi-Fi घुम्ने स्क्यान इन्टरफेसमा रहेको डेटा यातायातको मात्रामा आधारित अनुमति दिनुहोस्/नदिनुहोस्"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"लगर बफर आकारहरू"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"लग बफर प्रति लगर आकार चयन गर्नुहोस्"</string> diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml index 87d20c2e4ae3..ce25cc74fae7 100644 --- a/packages/SettingsLib/res/values-nl/strings.xml +++ b/packages/SettingsLib/res/values-nl/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Netwerken"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Certificering van draadloze weergave"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Uitgebreide wifi-logregistratie insch."</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agressieve handover van wifi naar mobiel"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Altijd roamingscans voor wifi toestaan"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiele data altijd actief"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardwareversnelling voor tethering"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Geef hostnaam van DNS-provider op"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Opties weergeven voor certificering van draadloze weergave"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Logniveau voor wifi verhogen, weergeven per SSID RSSI in wifi-kiezer"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Indien ingeschakeld, is wifi agressiever bij het overgeven van de gegevensverbinding aan mobiel wanneer het wifi-signaal zwak is"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Roamingscans voor wifi (niet) toestaan op basis van de hoeveelheid dataverkeer die aanwezig is bij de interface"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Logger-buffergrootten"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Kies Logger-grootten per logbuffer"</string> diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml index d870a99d9647..d64c30f4246c 100644 --- a/packages/SettingsLib/res/values-pa/strings.xml +++ b/packages/SettingsLib/res/values-pa/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"ਨੈੱਟਵਰਕਿੰਗ"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"ਵਾਇਰਲੈੱਸ ਡਿਸਪਲੇ ਪ੍ਰਮਾਣੀਕਰਨ"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"ਵਾਈ-ਫਾਈ ਵਰਬੋਸ ਲੌਗਿੰਗ ਚਾਲੂ ਕਰੋ"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"ਆਕਰਮਣਸ਼ੀਲ ਵਾਈ‑ਫਾਈ ਤੋਂ ਮੋਬਾਈਲ ਹੈਂਡਓਵਰ"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ਹਮੇਸ਼ਾਂ ਵਾਈ‑ਫਾਈ ਰੋਮ ਸਕੈਨਾਂ ਦੀ ਆਗਿਆ ਦਿਓ"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"ਮੋਬਾਈਲ ਡਾਟਾ ਹਮੇਸ਼ਾਂ ਕਿਰਿਆਸ਼ੀਲ"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"ਟੈਦਰਿੰਗ ਹਾਰਡਵੇਅਰ ਐਕਸੈੱਲਰੇਸ਼ਨ"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ਪ੍ਰਦਾਨਕ ਦਾ ਹੋਸਟਨਾਮ ਦਾਖਲ ਕਰੋ"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ਵਾਇਰਲੈੱਸ ਡਿਸਪਲੇ ਪ੍ਰਮਾਣੀਕਰਨ ਲਈ ਚੋਣਾਂ ਪ੍ਰਦਰਸ਼ਿਤ ਕਰੋ"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"ਵਾਈ‑ਫਾਈ ਲੌਗਿੰਗ ਪੱਧਰ ਵਧਾਓ, ਵਾਈ‑ਫਾਈ Picker ਵਿੱਚ ਪ੍ਰਤੀ SSID RSSI ਦਿਖਾਓ"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"ਜਦੋਂ ਯੋਗ ਬਣਾਇਆ ਹੋਵੇ, ਤਾਂ ਵਾਈ‑ਫਾਈ ਸਿਗਨਲ ਘੱਟ ਹੋਣ \'ਤੇ ਵਾਈ‑ਫਾਈ ਡਾਟਾ ਕਨੈਕਸ਼ਨ ਮੋਬਾਈਲ ਨੂੰ ਹੈਂਡ ਓਵਰ ਕਰਨ ਵਿੱਚ ਵੱਧ ਆਕਰਮਣਸ਼ੀਲ ਹੋਵੇਗਾ।"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ਇੰਟਰਫੇਸ ਤੇ ਮੌਜੂਦ ਡਾਟਾ ਟ੍ਰੈਫਿਕ ਦੀ ਮਾਤਰਾ ਦੇ ਆਧਾਰ ਤੇ ਵਾਈ-ਫਾਈ ਰੋਮ ਸਕੈਨ ਦੀ ਆਗਿਆ ਦਿਓ/ਅਸਵੀਕਾਰ ਕਰੋ"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"ਲੌਗਰ ਬਫ਼ਰ ਆਕਾਰ"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ਪ੍ਰਤੀ ਲੌਗ ਬਫ਼ਰ ਲੌਗਰ ਆਕਾਰ ਚੁਣੋ"</string> diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml index 7b66aa53bfbe..d50528dae95d 100644 --- a/packages/SettingsLib/res/values-pl/strings.xml +++ b/packages/SettingsLib/res/values-pl/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Sieci"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Wyświetlacz bezprzewodowy"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Szczegółowy dziennik Wi-Fi"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Przełączaj z Wi-Fi na sieć komórkową"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Zawsze szukaj Wi-Fi w roamingu"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilna transmisja danych zawsze aktywna"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Akceleracja sprzętowa tetheringu"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Wpisz nazwę hosta dostawcy DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Pokaż opcje certyfikacji wyświetlacza bezprzewodowego"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Zwiększ poziom rejestrowania Wi‑Fi, pokazuj według RSSI SSID w selektorze Wi‑Fi"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Po włączeniu połączenie danych będzie bardziej agresywnie przełączać się z Wi-Fi na sieć komórkową przy słabym sygnale Wi-Fi"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Zezwalaj/nie zezwalaj na wyszukiwanie sieci Wi-Fi w roamingu w zależności od natężenia ruchu"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Rozmiary bufora Rejestratora"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Wybierz rozmiary Rejestratora/bufor dziennika"</string> diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml index d99097a9b82f..67fda0390e50 100644 --- a/packages/SettingsLib/res/values-pt-rBR/strings.xml +++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Redes"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Certificação de Display sem fio"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Ativar registro extenso de Wi-Fi"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Mudança agressiva de Wi-Fi para móvel"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Sempre permitir verif. de roaming de Wi-Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Dados móveis sempre ativos"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleração de hardware de tethering"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Informe o nome do host do provedor de DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opções de certificação de Display sem fio"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar o nível de registro do Wi-Fi; mostrar conforme o RSSI de SSID na Seleção de Wi-Fi"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Quando ativada, o Wi-Fi será mais agressivo em passar a conexão de dados para móvel, quando o sinal de Wi-Fi estiver fraco"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permitir/proibir verificações de roaming de Wi-Fi com base no volume do tráfego de dados presente na interface"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Tamanhos de buffer de logger"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Sel. tam. de logger/buffer de log"</string> diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml index 8c7fbba34e12..d7496454c471 100644 --- a/packages/SettingsLib/res/values-pt-rPT/strings.xml +++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Redes"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Certificação de display sem fios"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Ativar o registo verboso de Wi-Fi"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Mudança brusca de Wi‑Fi para rede móvel"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir sempre a deteção de Wi-Fi em roaming"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Dados móveis sempre ativos"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleração de hardware para ligação (à Internet) via telemóvel"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introduza o nome de anfitrião do fornecedor DNS."</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opções da certificação de display sem fios"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar o nível de reg. de Wi-Fi, mostrar por RSSI de SSID no Selec. de Wi-Fi"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Se estiver ativado, o Wi-Fi será mais agressivo ao transmitir a lig. de dados para a rede móvel quando o sinal Wi-Fi estiver fraco"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permitir/impedir a deteção de Wi-Fi em roaming com base na quantidade de tráfego de dados presente na interface"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Tamanhos da memória intermédia do registo"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Selec. tam. reg. p/ mem. int. reg."</string> diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml index d99097a9b82f..67fda0390e50 100644 --- a/packages/SettingsLib/res/values-pt/strings.xml +++ b/packages/SettingsLib/res/values-pt/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Redes"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Certificação de Display sem fio"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Ativar registro extenso de Wi-Fi"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Mudança agressiva de Wi-Fi para móvel"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Sempre permitir verif. de roaming de Wi-Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Dados móveis sempre ativos"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleração de hardware de tethering"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Informe o nome do host do provedor de DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opções de certificação de Display sem fio"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar o nível de registro do Wi-Fi; mostrar conforme o RSSI de SSID na Seleção de Wi-Fi"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Quando ativada, o Wi-Fi será mais agressivo em passar a conexão de dados para móvel, quando o sinal de Wi-Fi estiver fraco"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permitir/proibir verificações de roaming de Wi-Fi com base no volume do tráfego de dados presente na interface"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Tamanhos de buffer de logger"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Sel. tam. de logger/buffer de log"</string> diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml index 1c6755077feb..1e91d8264f07 100644 --- a/packages/SettingsLib/res/values-ro/strings.xml +++ b/packages/SettingsLib/res/values-ro/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Conectare la rețele"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Certificare Ecran wireless"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Înregistrare prin Wi-Fi de volume mari de date"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Predare agresivă de la Wi-Fi la mobilă"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Se permite întotdeauna scanarea traficului Wi-Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Date mobile permanent active"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Accelerare hardware pentru tethering"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introduceți numele de gazdă al furnizorului de DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Afișați opțiunile pentru certificarea Ecran wireless"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Măriți niv. de înr. prin Wi‑Fi, afișați în fcț. de SSID RSSI în Selectorul Wi‑Fi"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Când este activată, Wi-Fi va fi mai agresivă la predarea conexiunii de date către rețeaua mobilă când semnalul Wi-Fi este slab"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permiteți/Nu permiteți scanarea traficului Wi-Fi în funcție de traficul de date din interfață"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Dimensiunile tamponului jurnalului"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Dimensiuni jurnal / tampon jurnal"</string> diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml index 4b1159441e97..693332f52e8f 100644 --- a/packages/SettingsLib/res/values-ru/strings.xml +++ b/packages/SettingsLib/res/values-ru/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Сети"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Серт. беспроводн. мониторов"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Подробный журнал Wi‑Fi"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Переключаться на мобильную сеть"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Всегда включать поиск сетей Wi-Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Не отключать мобильный Интернет"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Аппаратное ускорение в режиме модема"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Введите имя хоста поставщика услуг DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Показывать параметры сертификации беспроводных мониторов"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"При выборе Wi‑Fi указывать в журнале RSSI для каждого SSID"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Принудительно переключаться на мобильную сеть, если сигнал Wi-Fi слабый"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Включать или отключать поиск сетей Wi-Fi во время передачи данных в зависимости от объема трафика"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Размер буфера журнала"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Выберите размер буфера журнала"</string> diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml index 2ffe814dd476..6abd14da6f26 100644 --- a/packages/SettingsLib/res/values-si/strings.xml +++ b/packages/SettingsLib/res/values-si/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"ජාලකරණය"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"නොරැහැන් සංදර්ශක සහතිකය"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"විස්තරාත්මක Wi‑Fi ලොග් කිරීම සබල කරන්න"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"ආක්රමණික Wi‑Fi සිට ජංගම බාර දීම"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi රෝම් පරිලෝකන වෙතට සැමවිට අවසර දෙන්න"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"ජංගම දත්ත සැමවිට ක්රියාකාරීය"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"ටෙදරින් දෘඪාංග ත්වරණය"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS සැපයුම්කරුගේ සත්කාරක නම ඇතුළු කරන්න"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"නොරැහැන් සංදර්ශක සහතිකය සඳහා විකල්ප පෙන්වන්න"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi ලොග් මට්ටම වැඩි කරන්න, Wi‑Fi තෝරනයෙහි SSID RSSI අනුව පෙන්වන්න"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"සබල විට Wi‑Fi සිග්නලය අඩු විට Wi‑Fi දත්ත සම්බන්ධතාවය ජංගම වෙත භාර දීමට වඩා ආක්රමණික වේ"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"අතුරු මුහුණතෙහි ඇති දත්ත තදබදය අනුව Wi‑Fi රෝම් පරිලෝකන වෙත ඉඩ දෙන්න/නොදෙන්න"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"ලෝගයේ අන්තරාවක ප්රමාණය"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ලොග අන්තරාවකට ලෝගයේ ප්රමාණය තෝරන්න"</string> diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml index 0cefd71832c4..8cc2dac2d304 100644 --- a/packages/SettingsLib/res/values-sk/strings.xml +++ b/packages/SettingsLib/res/values-sk/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Siete"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Certifikácia bezdrôtového zobrazenia"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Podrobné denníky Wi‑Fi"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agres. odovzdávať Wi‑Fi na mobilnú sieť"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vždy povoliť funkciu Wi‑Fi Roam Scans"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilné dáta ponechať vždy aktívne"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardvérovú akcelerácia pre tethering"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Zadajte názov hostiteľa poskytovateľa DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Zobraziť možnosti certifikácie bezdrôtového zobrazenia"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Zvýšiť úroveň denníkov Wi‑Fi, zobrazovať podľa SSID RSSI pri výbere siete Wi‑Fi"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Keď túto možnosť zapnete, Wi‑Fi bude agresívnejšie odovzdávať dátové pripojenie na mobilnú sieť vtedy, keď bude slabý signál Wi‑Fi"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Povoliť alebo zakázať funkciu Wifi Roam Scans na základe objemu prenosu údajov v rozhraní"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Vyrovnávacia pamäť nástroja denníkov"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Veľkosť vyrovnávacej pamäte nástroja denníkov"</string> diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml index 0864d5b921f2..af8eb6e11d6f 100644 --- a/packages/SettingsLib/res/values-sl/strings.xml +++ b/packages/SettingsLib/res/values-sl/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Omrežja"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Potrdilo brezžičnega zaslona"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Omogoči podrob. zapis. dnevnika za Wi-Fi"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Odločen prehod iz Wi-Fi-ja v mobil. omr."</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vedno omogoči iskanje omrežij Wi-Fi za gostovanje"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Prenos podatkov v mobilnem omrežju je vedno aktiven"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Strojno pospeševanje za internetno povezavo prek mobilnega telefona"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Vnesite ime gostitelja pri ponudniku strežnika DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Pokaži možnosti za potrdilo brezžičnega zaslona"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povečaj raven zapis. dnev. za Wi-Fi; v izbir. Wi‑Fi-ja pokaži glede na SSID RSSI"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Če je ta možnost omogočena, Wi-Fi odločneje preda podatkovno povezavo mobilnemu omrežju, ko je signal Wi-Fi šibek."</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Omogoči/onemogoči iskanje omrežij Wi-Fi za gostovanje glede na količino podatkovnega prometa pri vmesniku"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Velikosti medpomn. zapisov. dnevnika"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Izberite velikost medpomnilnika dnevnika"</string> diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml index 63da6ffd2a63..88b1057739bc 100644 --- a/packages/SettingsLib/res/values-sq/strings.xml +++ b/packages/SettingsLib/res/values-sq/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Rrjetet"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Certifikimi i ekranit valor"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Aktivizo hyrjen Wi-Fi Verbose"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Dorëzimi agresiv i Wi‑Fi te rrjeti celular"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Lejo gjithmonë skanimet për Wi-Fi edhe kur je në lëvizje"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Të dhënat celulare gjithmonë aktive"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Përshpejtimi i harduerit për ndarjen"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Fut emrin e pritësit të ofruesit të DNS-së"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Shfaq opsionet për certifikimin e ekranit valor"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Rrit nivelin regjistrues të Wi‑Fi duke shfaqur SSID RSSI-në te Zgjedhësi i Wi‑Fi"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Kur ky funksion aktivizohet, Wi‑Fi bëhet më agresiv në kalimin e lidhjes së të dhënave te rrjeti celular, në rastet kur sinjali Wi‑Fi është i dobët"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Lejo/Ndalo skanimet për Wi‑Fi në roaming, bazuar në sasinë e trafikut të të dhënave të pranishme në ndërfaqe"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Madhësitë e regjistruesit"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Përzgjidh madhësitë e regjistruesit"</string> diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml index 4c7aed8e29a3..362fc1fb77dd 100644 --- a/packages/SettingsLib/res/values-sr/strings.xml +++ b/packages/SettingsLib/res/values-sr/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Умрежавање"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Сертификација бежичног екрана"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Омогући детаљнију евиденцију за Wi‑Fi"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Агресиван прелаз са Wi‑Fi мреже на мобилну"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Увек дозволи скенирање Wi‑Fi-ја у ромингу"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Мобилни подаци су увек активни"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Хардверско убрзање привезивања"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Унесите име хоста добављача услуге DNS-а"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Приказ опција за сертификацију бежичног екрана"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Повећава ниво евидентирања за Wi‑Fi. Приказ по SSID RSSI-у у бирачу Wi‑Fi мреже"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Кад се омогући, Wi‑Fi ће бити агресивнији при пребацивању мреже за пренос података на мобилну ако је Wi‑Fi сигнал слаб"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Дозволи/забрани скенирање Wi-Fi-ја у ромингу на основу присутног протока података на интерфејсу"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Величине бафера података у програму за евидентирање"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Изаберите величине по баферу евиденције"</string> diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml index e44dcd8dde6d..230dfeefdd8e 100644 --- a/packages/SettingsLib/res/values-sv/strings.xml +++ b/packages/SettingsLib/res/values-sv/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Nätverk"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Certifiering för Wi-Fi-skärmdelning"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Aktivera utförlig loggning för Wi-Fi"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aggressiv överlämning fr. Wi-Fi t. mobil"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Tillåt alltid sökning efter Wi-Fi-roaming"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobildata alltid aktiverad"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Maskinvaruacceleration för internetdelning"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Ange värdnamn för DNS-leverantör"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Visa certifieringsalternativ för Wi-Fi-skärmdelning"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Öka loggningsnivån för Wi-Fi, visa per SSID RSSI i Wi‑Fi Picker"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"När funktionen har aktiverats kommer dataanslutningen lämnas över från Wi-Fi till mobilen på ett aggressivare sätt när Wi-Fi-signalen är svag"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Tillåt/tillåt inte sökning efter Wi-Fi-roaming utifrån mängden datatrafik i gränssnittet"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Buffertstorlekar för logg"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Välj loggstorlekar per loggbuffert"</string> diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml index 66cfda8b8079..1d462603750b 100644 --- a/packages/SettingsLib/res/values-sw/strings.xml +++ b/packages/SettingsLib/res/values-sw/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Mtandao"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Chaguo za cheti cha kuonyesha pasiwaya"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Washa Uwekaji kumbukumbu za WiFi kutumia Sauti"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Ukabidhi hima kutoka Wifi kwenda mtandao wa simu"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Ruhusu Uchanganuzi wa Matumizi ya Mitandao mingine"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Iendelee kutumia data ya simu"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Kuongeza kasi kwa kutumia maunzi ili kusambaza mtandao"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Weka jina la mpangishi wa huduma za DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Onyesha chaguo za cheti cha kuonyesha pasiwaya"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Ongeza hatua ya uwekaji kumbukumbu ya Wi-Fi, onyesha kwa kila SSID RSSI kwenye Kichukuzi cha Wi-Fi"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Ikiwashwa, Wi-Fi itakabidhi kwa hima muunganisho wa data kwa mtandao wa simu, wakati mtandao wa Wi-Fi si thabiti"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Ruhusu au Zuia Uchanganuzi wa Matumizi ya Mitandao mingine ya Wifi kulingana na kiasi cha trafiki ya data kilicho kwenye kiolesura"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Ukubwa wa kiweka bafa ya kumbukumbu"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Chagua ukubwa wa kila Kumbukumbu"</string> diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml index dd218c61ab15..e9fd79bfe9a7 100644 --- a/packages/SettingsLib/res/values-ta/strings.xml +++ b/packages/SettingsLib/res/values-ta/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"நெட்வொர்க்கிங்"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"வயர்லெஸ் காட்சிக்கான சான்றிதழ்"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"வைஃபை அதிவிவர நுழைவை இயக்கு"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"ஒத்துழைக்காத வைஃபையிலிருந்து மொபைல் தரவிற்கு மாறு"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"எப்போதும் வைஃபை ரோமிங் ஸ்கேன்களை அனுமதி"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"மொபைல் டேட்டாவை எப்போதும் இயக்கத்திலேயே வை"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"வன்பொருள் விரைவுப்படுத்துதல் இணைப்பு முறை"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS வழங்குநரின் ஹோஸ்ட் பெயரை உள்ளிடவும்"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"வயர்லெஸ் காட்சி சான்றுக்கான விருப்பங்களைக் காட்டு"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wifi நுழைவு அளவை அதிகரித்து, வைஃபை தேர்வியில் ஒவ்வொன்றிற்கும் SSID RSSI ஐ காட்டுக"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"இயக்கப்பட்டதும், வைஃபை சிக்னல் குறையும் போது, வைஃபை முழுமையாக ஒத்துழைக்காமல் இருந்தால் மொபைல் தரவிற்கு மாறும்"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"இடைமுகத்தில் உள்ள ட்ராஃபிக் தரவின் அளவைப் பொறுத்து வைஃபை ரோமிங் ஸ்கேன்களை அனுமதி/அனுமதிக்காதே"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"லாகர் பஃபர் அளவுகள்"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"லாக் பஃபர் ஒன்றிற்கு லாகர் அளவுகளைத் தேர்வுசெய்க"</string> diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml index b21eb8c8f8c0..c2b738ac9898 100644 --- a/packages/SettingsLib/res/values-te/strings.xml +++ b/packages/SettingsLib/res/values-te/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"నెట్వర్కింగ్"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"వైర్లెస్ ప్రదర్శన ప్రమాణీకరణ"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi విశదీకృత లాగింగ్ను ప్రారంభించండి"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"మొబైల్కి మార్చేలా చురుకైన Wi‑Fi"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi సంచార స్కాన్లను ఎల్లప్పుడూ అనుమతించు"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"మొబైల్ డేటాని ఎల్లప్పుడూ సక్రియంగా ఉంచు"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"టెథెరింగ్ హార్డ్వేర్ వేగవృద్ధి"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ప్రదాత యొక్క హోస్ట్పేరును నమోదు చేయండి"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"వైర్లెస్ ప్రదర్శన సర్టిఫికెట్ కోసం ఎంపికలను చూపు"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi ఎంపికలో SSID RSSI ప్రకారం చూపబడే Wi‑Fi లాగింగ్ స్థాయిని పెంచండి"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"ప్రారంభించబడినప్పుడు, Wi‑Fi సిగ్నల్ బలహీనంగా ఉంటే డేటా కనెక్షన్ను మొబైల్కి మార్చేలా Wi‑Fi చురుగ్గా వ్యవహరిస్తుంది"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ఇంటర్ఫేస్లో ఉండే డేటా ట్రాఫిక్ పరిమాణం ఆధారంగా Wi‑Fi సంచార స్కాన్లను అనుమతించు/నిరాకరించు"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"లాగర్ బఫర్ పరిమాణాలు"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"లాగ్ బఫర్కి లాగర్ పరిమా. ఎంచుకోండి"</string> diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml index 447b188a4b89..57b12a5601a7 100644 --- a/packages/SettingsLib/res/values-th/strings.xml +++ b/packages/SettingsLib/res/values-th/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"เครือข่าย"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"การรับรองการแสดงผลแบบไร้สาย"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"เปิดใช้การบันทึกรายละเอียด Wi-Fi"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"สลับ Wi‑Fi เป็นมือถือเมื่อสัญญาณอ่อน"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ใช้การสแกน Wi-Fi ข้ามเครือข่ายเสมอ"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"เปิดใช้อินเทอร์เน็ตมือถือเสมอ"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"การเร่งฮาร์ดแวร์การเชื่อมต่ออินเทอร์เน็ตผ่านมือถือ"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"ป้อนชื่อโฮสต์ของผู้ให้บริการ DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"แสดงตัวเลือกสำหรับการรับรองการแสดงผล แบบไร้สาย"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"เพิ่มระดับการบันทึก Wi‑Fi แสดงต่อ SSID RSSI ในตัวเลือก Wi‑Fi"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"เมื่อเปิดใช้แล้ว Wi-Fi จะส่งผ่านการเชื่อมต่อข้อมูลไปยังเครือข่ายมือถือเมื่อสัญญาณ Wi-Fi อ่อน"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"อนุญาต/ไม่อนุญาตการสแกน Wi-Fi ข้ามเครือข่าย ตามปริมาณข้อมูลการเข้าชมที่ปรากฏในอินเทอร์เฟซ"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"ขนาดบัฟเฟอร์ของ Logger"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"เลือกขนาด Logger ต่อบัฟเฟอร์ไฟล์บันทึก"</string> diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml index a5e0b8960239..72261afd43ea 100644 --- a/packages/SettingsLib/res/values-tl/strings.xml +++ b/packages/SettingsLib/res/values-tl/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Networking"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Certification ng wireless display"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"I-enable ang Pagla-log sa Wi‑Fi Verbose"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agresibong paglipat ng Wi‑Fi sa mobile"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Palaging payagan ang Mga Pag-scan sa Roaming ng Wi‑Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Palaging aktibo ang mobile data"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardware acceleration para sa pag-tether"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Ilagay ang hostname ng DNS provider"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Ipakita ang mga opsyon para sa certification ng wireless display"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Pataasin ang antas ng Wi‑Fi logging, ipakita sa bawat SSID RSSI sa Wi‑Fi Picker"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Kapag na-enable, magiging mas agresibo ang Wi‑Fi sa paglipat sa koneksyon ng mobile data kapag mahina ang signal ng Wi‑Fi"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Payagan/Huwag payagan ang Mga Pag-scan sa Roaming ng Wi‑Fi batay sa dami ng trapiko ng data na mayroon sa interface"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Mga laki ng buffer ng Logger"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Pumili ng mga laki ng Logger bawat log buffer"</string> diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml index e6bba5be7a4a..948e4e5c9465 100644 --- a/packages/SettingsLib/res/values-tr/strings.xml +++ b/packages/SettingsLib/res/values-tr/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Ağ işlemleri"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Kablosuz ekran sertifikası"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Kablosuz Ayrıntılı Günlük Kaydını etkinleştir"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Kablosuzdan mobil ağa agresif geçiş"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Kablosuz Dolaşım Taramalarına daima izin ver"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobil veri her zaman etkin"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering donanım hızlandırıcısı"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS sağlayıcının ana makine adını gir"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Kablosuz ekran sertifikası seçeneklerini göster"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Kablosuz günlük kaydı seviyesini artır. Kablosuz Seçici\'de her bir SSID RSSI için göster."</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Etkinleştirildiğinde, kablosuz ağ sinyali zayıfken veri bağlantısının mobil ağa geçirilmesinde daha agresif olunur"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Arayüzde mevcut veri trafiği miktarına bağlı olarak Kablosuz Dolaşım Taramalarına İzin Verin/Vermeyin"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Günlük Kaydedici arabellek boyutları"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Gün. arabel. başına Gün. Kayd. boyutunu seç"</string> diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml index 65f39edd1f5a..664fda7a2413 100644 --- a/packages/SettingsLib/res/values-uk/strings.xml +++ b/packages/SettingsLib/res/values-uk/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Мережі"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Сертифікація бездрот. екрана"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Докладний запис у журнал Wi-Fi"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Перемикатися з Wi-Fi на мобільну мережу"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Завжди шукати мережі Wi-Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Не вимикати мобільне передавання даних"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Апаратне прискорення під час використання телефона в режимі модема"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Введіть ім’я хосту постачальника послуг DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Показати параметри сертифікації бездротового екрана"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Показувати в журналі RSSI для кожного SSID під час вибору Wi-Fi"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Примусово перемикатися на мобільну мережу, коли сигнал Wi-Fi слабкий"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Дозволити чи заборонити Wi-Fi шукати роумінг на основі обсягу трафіку даних в інтерфейсі"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Розміри буфера журналу"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Виберіть розміри буфера журналу"</string> diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml index 7830bb86ce72..226b862fc6fb 100644 --- a/packages/SettingsLib/res/values-ur/strings.xml +++ b/packages/SettingsLib/res/values-ur/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"نیٹ ورکنگ"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"وائرلیس ڈسپلے سرٹیفیکیشن"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi وربوس لاگنگ فعال کریں"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi‑Fi سے موبائل کو جارحانہ ہینڈ اوور"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ہمیشہ Wi‑Fi روم اسکینز کی اجازت دیں"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"موبائل ڈیٹا ہمیشہ فعال رکھیں"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"ٹیدرنگ ہارڈویئر سرعت کاری"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS فراہم کنندہ کے میزبان کا نام درج کریں"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"وائرلیس ڈسپلے سرٹیفیکیشن کیلئے اختیارات دکھائیں"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi لاگنگ لیول میں اضافہ کریں، Wi‑Fi منتخب کنندہ میں فی SSID RSSI دکھائیں"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"فعال کئے جانے پر، جب Wi‑Fi سگنل کمزور ہوگا، تو Wi‑Fi موبائل پر ڈیٹا کنکشن بھیجنے کیلئے مزید جارحانہ کارروائی کرے گا"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"انٹرفیس پر موجود ڈیٹا ٹریفک کی مقدار کی بنیاد پر Wi‑Fi روم اسکینز کی اجازت دیں/اجازت نہ دیں"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"لاگر بفر کے سائز"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"فی لاگ بفر لاگر کے سائز منتخب کریں"</string> diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml index acaaaf1b8f5d..fdb3ef478467 100644 --- a/packages/SettingsLib/res/values-uz/strings.xml +++ b/packages/SettingsLib/res/values-uz/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Tarmoqlar"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Simsiz monitor sertifikatlari"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Batafsil Wi-Fi jurnali"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Mobil internetga o‘tish"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi-Fi tarmoqlarini qidirishga doim ruxsat"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobil internet doim yoniq tursin"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Modem rejimida apparatli tezlashtirish"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS provayderining host nomini kiriting"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Simsiz monitorlarni sertifikatlash parametrini ko‘rsatish"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fi ulanishini tanlashda har bir SSID uchun jurnalda ko‘rsatilsin"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Agar ushbu funksiya yoqilsa, Wi-Fi signali past bo‘lganda internetga ulanish majburiy ravishda mobil internetga o‘tkaziladi"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Ma’lumotlarni uzatish vaqtida trafik hajmiga qarab Wi-Fi tarmoqlarni qidirish funksiyasini yoqish yoki o‘chirish"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Jurnal buferi hajmi"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Jurnal xotirasi hajmini tanlang"</string> diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml index 7732b54c2c6d..a7a585583a84 100644 --- a/packages/SettingsLib/res/values-vi/strings.xml +++ b/packages/SettingsLib/res/values-vi/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Mạng"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Chứng nhận hiển thị không dây"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Bật ghi nhật ký chi tiết Wi‑Fi"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Chuyển vùng Wi‑Fi tích cực sang mạng DĐ"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Luôn cho phép quét chuyển vùng Wi‑Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Dữ liệu di động luôn hiện hoạt"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Tăng tốc phần cứng cho chia sẻ kết nối"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Nhập tên máy chủ của nhà cung cấp DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Hiển thị tùy chọn chứng nhận hiển thị không dây"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Tăng mức ghi nhật ký Wi‑Fi, hiển thị mỗi SSID RSSI trong bộ chọn Wi‑Fi"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Khi được bật, Wi‑Fi sẽ tích cực hơn trong việc chuyển vùng kết nối dữ liệu sang mạng di động khi tín hiệu Wi‑Fi yếu"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Cho phép/Không cho phép quét chuyển vùng Wi‑Fi dựa trên lưu lượng truy cập dữ liệu có tại giao diện"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Kích cỡ tải trình ghi"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Chọn kích thước Trình ghi/lần tải nhật ký"</string> diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml index f036eae1ff0c..5a1d0671cba6 100644 --- a/packages/SettingsLib/res/values-zh-rCN/strings.xml +++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"网络"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"无线显示认证"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"启用WLAN详细日志记录功能"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"主动从 WLAN 网络切换到移动数据网络"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"一律允许WLAN漫游扫描"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"始终开启移动数据网络"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"网络共享硬件加速"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"输入 DNS 提供商的主机名"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"显示无线显示认证选项"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"提升WLAN日志记录级别(在WLAN选择器中显示每个SSID的RSSI)"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"开启此设置后,系统会在 WLAN 信号较弱时,主动将网络模式从 WLAN 网络切换到移动数据网络"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"根据接口中目前的数据流量允许/禁止WLAN漫游扫描"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"日志记录器缓冲区大小"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"选择每个日志缓冲区的日志记录器大小"</string> diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml index d57a8fd01196..acc3bb83226c 100644 --- a/packages/SettingsLib/res/values-zh-rHK/strings.xml +++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"網絡"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"無線螢幕分享認證"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"啟用 Wi‑Fi 詳細記錄"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"加強 Wi-Fi 至流動數據轉換"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"永遠允許 Wi-Fi 漫遊掃描"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"一律保持啟用流動數據"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"網絡共享硬件加速"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"輸入網域名稱系統 (DNS) 供應商的主機名稱"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"顯示無線螢幕分享認證的選項"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"讓 Wi‑Fi 記錄功能升級,在 Wi‑Fi 選擇器中依每個 SSID RSSI 顯示 Wi‑Fi 詳細紀錄"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"啟用後,Wi-Fi 連線會在訊號不穩定的情況下更積極轉換成流動數據連線"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"根據介面中目前的數據流量允許/禁止 WiFi 漫遊掃描"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"記錄器緩衝區空間"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"選取每個記錄緩衝區的記錄器空間"</string> diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml index 5a329fa9c25f..775b92877628 100644 --- a/packages/SettingsLib/res/values-zh-rTW/strings.xml +++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"網路連線"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"無線螢幕分享認證"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"啟用 Wi‑Fi 詳細紀錄設定"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi-Fi 至行動數據轉換強化"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"一律允許 Wi-Fi 漫遊掃描"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"行動數據連線一律保持啟用狀態"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"數據連線硬體加速"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"輸入 DNS 供應商的主機名稱"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"顯示無線螢幕分享認證的選項"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"讓 Wi‑Fi 記錄功能升級,在 Wi‑Fi 選擇器中依每個 SSID RSSI 顯示 Wi‑Fi 詳細紀錄"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"啟用時,Wi-Fi 連線在訊號不穩的情況下會更積極轉換成行動數據連線"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"根據介面中目前的數據流量允許/禁止 Wi-Fi 漫遊掃描"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"紀錄器緩衝區空間"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"選取每個紀錄緩衝區的紀錄器空間"</string> diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml index 3649ba24ebd0..13b16037a549 100644 --- a/packages/SettingsLib/res/values-zu/strings.xml +++ b/packages/SettingsLib/res/values-zu/strings.xml @@ -196,7 +196,6 @@ <string name="debug_networking_category" msgid="7044075693643009662">"Ukunethiwekha"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"Ukunikezwa isitifiketi sokubukeka okungenantambo"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Nika amandlaukungena kwe-Wi-Fi Verbose"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Ukudluliselwa okunamandla kakhulu kwe-Wi-Fi ukuya kuselula"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vumela njalo ukuskena kokuzula kwe-Wi-Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Idatha yeselula ihlala isebenza"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"I-Tethering hardware acceleration"</string> @@ -223,7 +222,6 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Faka igama lomsingathi womhlinzeki we-DNS"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Bonisa izinketho zokunikeza isitifiketi ukubukeka okungenantambo"</string> <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"khuphula izinga lokungena le-Wi-Fi, bonisa nge-SSID RSSI engayodwana kusikhethi se-Wi-Fi"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Uma inikwe amandla, i-Wi-Fi izoba namandla kakhulu ekudluliseleni ukuxhumeka kwedatha kuselula, uma isignali ye-Wi-Fi iphansi"</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Vumela/Ungavumeli ukuskena kokuzula kwe-Wi-Fi okususelwa kunani ledatha yethrafikhi ekhona ekusebenzisaneni"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"Amasayizi weloga ngebhafa"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Khetha amasayizi weloga ngebhafa ngayinye yelogu"</string> diff --git a/packages/SystemUI/res/anim/car_user_switcher_close_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_close_animation.xml new file mode 100644 index 000000000000..ed637a7adcbf --- /dev/null +++ b/packages/SystemUI/res/anim/car_user_switcher_close_animation.xml @@ -0,0 +1,20 @@ +<!-- 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. +--> +<animator xmlns:android="http://schemas.android.com/apk/res/android" + android:duration="133" + android:valueType="intType" + android:valueFrom="@dimen/car_user_switcher_container_height" + android:valueTo="0" + android:interpolator="@android:interpolator/fast_out_slow_in" /> diff --git a/packages/SystemUI/res/anim/car_user_switcher_close_icon_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_close_icon_animation.xml new file mode 100644 index 000000000000..227c981cb72a --- /dev/null +++ b/packages/SystemUI/res/anim/car_user_switcher_close_icon_animation.xml @@ -0,0 +1,24 @@ +<!-- 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. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android"> + + <objectAnimator + android:duration="167" + android:propertyName="rotation" + android:valueType="floatType" + android:valueFrom="180" + android:valueTo="0" + android:interpolator="@android:interpolator/fast_out_slow_in" /> +</set>
\ No newline at end of file diff --git a/packages/SystemUI/res/anim/car_user_switcher_close_name_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_close_name_animation.xml new file mode 100644 index 000000000000..5901ff41735c --- /dev/null +++ b/packages/SystemUI/res/anim/car_user_switcher_close_name_animation.xml @@ -0,0 +1,23 @@ +<!-- 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. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android"> + + <objectAnimator + android:duration="83" + android:propertyName="alpha" + android:valueType="floatType" + android:valueFrom="0" + android:valueTo="1" /> +</set>
\ No newline at end of file diff --git a/packages/SystemUI/res/anim/car_user_switcher_close_pages_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_close_pages_animation.xml new file mode 100644 index 000000000000..41cbe4b104c3 --- /dev/null +++ b/packages/SystemUI/res/anim/car_user_switcher_close_pages_animation.xml @@ -0,0 +1,23 @@ +<!-- 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. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android"> + + <objectAnimator + android:duration="83" + android:propertyName="alpha" + android:valueType="floatType" + android:valueFrom="1" + android:valueTo="0" /> +</set>
\ No newline at end of file diff --git a/packages/SystemUI/res/anim/car_user_switcher_close_pod_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_close_pod_animation.xml new file mode 100644 index 000000000000..341e7e0cdfe9 --- /dev/null +++ b/packages/SystemUI/res/anim/car_user_switcher_close_pod_animation.xml @@ -0,0 +1,24 @@ +<!-- 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. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android" + android:ordering="together" > + + <objectAnimator + android:duration="50" + android:propertyName="alpha" + android:valueType="floatType" + android:valueFrom="1" + android:valueTo="0" /> +</set>
\ No newline at end of file diff --git a/packages/SystemUI/res/anim/car_user_switcher_open_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_open_animation.xml new file mode 100644 index 000000000000..6ae74131584d --- /dev/null +++ b/packages/SystemUI/res/anim/car_user_switcher_open_animation.xml @@ -0,0 +1,20 @@ +<!-- 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. +--> +<animator xmlns:android="http://schemas.android.com/apk/res/android" + android:duration="200" + android:valueType="intType" + android:valueFrom="0" + android:valueTo="@dimen/car_user_switcher_container_height" + android:interpolator="@android:interpolator/fast_out_slow_in" /> diff --git a/packages/SystemUI/res/anim/car_user_switcher_open_icon_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_open_icon_animation.xml new file mode 100644 index 000000000000..06ac9e359b57 --- /dev/null +++ b/packages/SystemUI/res/anim/car_user_switcher_open_icon_animation.xml @@ -0,0 +1,24 @@ +<!-- 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. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android"> + + <objectAnimator + android:duration="167" + android:propertyName="rotation" + android:valueType="floatType" + android:valueFrom="0" + android:valueTo="180" + android:interpolator="@android:interpolator/fast_out_slow_in" /> +</set>
\ No newline at end of file diff --git a/packages/SystemUI/res/anim/car_user_switcher_open_name_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_open_name_animation.xml new file mode 100644 index 000000000000..4baefb83a4ef --- /dev/null +++ b/packages/SystemUI/res/anim/car_user_switcher_open_name_animation.xml @@ -0,0 +1,24 @@ +<!-- 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. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android"> + + <objectAnimator + android:duration="83" + android:startOffset="83" + android:propertyName="alpha" + android:valueType="floatType" + android:valueFrom="1" + android:valueTo="0" /> +</set>
\ No newline at end of file diff --git a/packages/SystemUI/res/anim/car_user_switcher_open_pages_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_open_pages_animation.xml new file mode 100644 index 000000000000..2d0deb95da59 --- /dev/null +++ b/packages/SystemUI/res/anim/car_user_switcher_open_pages_animation.xml @@ -0,0 +1,24 @@ +<!-- 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. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android"> + + <objectAnimator + android:duration="83" + android:startOffset="83" + android:propertyName="alpha" + android:valueType="floatType" + android:valueFrom="0" + android:valueTo="1" /> +</set>
\ No newline at end of file diff --git a/packages/SystemUI/res/anim/car_user_switcher_open_pod_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_open_pod_animation.xml new file mode 100644 index 000000000000..3315220a60ef --- /dev/null +++ b/packages/SystemUI/res/anim/car_user_switcher_open_pod_animation.xml @@ -0,0 +1,33 @@ +<!-- 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. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android" + android:ordering="together" > + + <objectAnimator + android:duration="167" + android:startOffset="67" + android:propertyName="translationY" + android:valueType="floatType" + android:valueFrom="@dimen/car_user_switcher_container_anim_height" + android:valueTo="0" + android:interpolator="@android:interpolator/fast_out_slow_in" /> + <objectAnimator + android:duration="83" + android:startOffset="117" + android:propertyName="alpha" + android:valueType="floatType" + android:valueFrom="0" + android:valueTo="1" /> +</set>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/car_ic_arrow.xml b/packages/SystemUI/res/drawable/car_ic_arrow.xml index 2c5ad27fe292..d400ed8c7707 100644 --- a/packages/SystemUI/res/drawable/car_ic_arrow.xml +++ b/packages/SystemUI/res/drawable/car_ic_arrow.xml @@ -1,5 +1,5 @@ <!-- - ~ 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. diff --git a/packages/SystemUI/res/drawable/car_ic_arrow_drop_up.xml b/packages/SystemUI/res/drawable/car_ic_arrow_drop_up.xml new file mode 100644 index 000000000000..33a512e31675 --- /dev/null +++ b/packages/SystemUI/res/drawable/car_ic_arrow_drop_up.xml @@ -0,0 +1,24 @@ +<!-- + ~ Copyright (C) 2015 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="48.0dp" + android:height="48.0dp" + android:viewportWidth="48.0" + android:viewportHeight="48.0"> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M14 28l10-10 10 10z"/> +</vector> diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml index 2f16516a6fea..0ee40d7ae47b 100644 --- a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml +++ b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml @@ -15,27 +15,40 @@ limitations under the License. --> -<LinearLayout +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="vertical" + android:clipChildren="false" + android:alpha="0" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:gravity="center" > + android:layout_height="@dimen/car_fullscreen_user_pod_height" + android:layout_gravity="center_horizontal|bottom" > <ImageView android:id="@+id/user_avatar" - android:layout_gravity="center" + android:layout_centerHorizontal="true" + android:layout_marginTop="@dimen/car_fullscreen_user_pod_margin_image_top" android:layout_width="@dimen/car_fullscreen_user_pod_image_avatar_width" - android:layout_height="@dimen/car_fullscreen_user_pod_image_avatar_height" /> + android:layout_height="@dimen/car_fullscreen_user_pod_image_avatar_height" + android:layout_above="@id/user_name" /> <TextView android:id="@+id/user_name" android:layout_width="@dimen/car_fullscreen_user_pod_width" android:layout_height="wrap_content" android:layout_marginTop="@dimen/car_fullscreen_user_pod_margin_name_top" android:layout_marginBottom="@dimen/car_fullscreen_user_pod_margin_name_bottom" - android:textSize="@dimen/car_fullscreen_user_pod_text_size" + android:textSize="@dimen/car_fullscreen_user_pod_name_text_size" android:textColor="@color/qs_user_detail_name" android:ellipsize="end" android:singleLine="true" android:gravity="center_horizontal" - android:layout_gravity="center_horizontal" /> -</LinearLayout> + android:layout_above="@id/device_name" /> + + <TextView android:id="@+id/device_name" + android:layout_width="@dimen/car_fullscreen_user_pod_width" + android:layout_height="wrap_content" + android:textSize="@dimen/car_fullscreen_user_pod_device_text_size" + android:textColor="@color/qs_user_detail_name" + android:ellipsize="end" + android:singleLine="true" + android:gravity="center_horizontal" + android:layout_alignParentBottom="true" /> +</RelativeLayout> diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_pod_container.xml b/packages/SystemUI/res/layout/car_fullscreen_user_pod_container.xml index 99d010f2ac2b..d666a203298f 100644 --- a/packages/SystemUI/res/layout/car_fullscreen_user_pod_container.xml +++ b/packages/SystemUI/res/layout/car_fullscreen_user_pod_container.xml @@ -16,10 +16,10 @@ --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:clipChildren="false" android:layout_width="match_parent" android:layout_height="wrap_content" - android:gravity="center" - android:layout_gravity="center" > + android:gravity="center" > <!-- car_fullscreen_user_pods will be dynamically added here. --> </LinearLayout> diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml b/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml index 257e2814bb65..478b65642689 100644 --- a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml +++ b/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml @@ -54,13 +54,13 @@ android:layout_height="wrap_content" android:layout_marginLeft="@dimen/car_margin" android:layout_marginRight="@dimen/car_margin" + android:layout_marginBottom="@dimen/car_user_grid_margin_bottom" android:layout_centerInParent="true" /> <com.android.systemui.statusbar.car.PageIndicator android:id="@+id/user_switcher_page_indicator" android:layout_width="match_parent" android:layout_height="@dimen/car_page_indicator_dot_diameter" - android:layout_marginTop="@dimen/car_page_indicator_margin_top" android:layout_below="@+id/user_grid" /> <Button diff --git a/packages/SystemUI/res/layout/car_qs_footer.xml b/packages/SystemUI/res/layout/car_qs_footer.xml index 044090be9f5d..3afd4ea33039 100644 --- a/packages/SystemUI/res/layout/car_qs_footer.xml +++ b/packages/SystemUI/res/layout/car_qs_footer.xml @@ -35,7 +35,6 @@ android:layout_centerVertical="true" android:layout_width="@dimen/car_qs_footer_icon_width" android:layout_height="@dimen/car_qs_footer_icon_height" - android:layout_marginRight="@dimen/car_qs_footer_user_switch_margin_right" android:background="@drawable/ripple_drawable" android:focusable="true"> @@ -47,6 +46,18 @@ android:scaleType="fitCenter"/> </com.android.systemui.statusbar.phone.MultiUserSwitch> + <ImageView + android:id="@+id/user_switch_expand_icon" + android:layout_height="match_parent" + android:layout_width="@dimen/car_qs_footer_user_switch_icon_width" + android:layout_centerVertical="true" + android:layout_toEndOf="@+id/multi_user_switch" + android:layout_marginLeft="@dimen/car_qs_footer_user_switch_icon_margin" + android:layout_marginRight="@dimen/car_qs_footer_user_switch_icon_margin" + android:src="@drawable/car_ic_arrow_drop_up" + android:scaleType="fitCenter"> + </ImageView> + <TextView android:id="@+id/user_name" android:layout_width="wrap_content" android:layout_height="wrap_content" @@ -54,7 +65,7 @@ android:textColor="@color/car_qs_footer_user_name_color" android:gravity="start|center_vertical" android:layout_centerVertical="true" - android:layout_toEndOf="@id/multi_user_switch" /> + android:layout_toEndOf="@id/user_switch_expand_icon" /> <com.android.systemui.statusbar.phone.SettingsButton android:id="@+id/settings_button" diff --git a/packages/SystemUI/res/layout/car_qs_panel.xml b/packages/SystemUI/res/layout/car_qs_panel.xml index 4cb0fd5fecfb..7844cac43f9a 100644 --- a/packages/SystemUI/res/layout/car_qs_panel.xml +++ b/packages/SystemUI/res/layout/car_qs_panel.xml @@ -16,6 +16,7 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/quick_settings_container" + android:clipChildren="false" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/car_qs_background_primary" @@ -26,10 +27,32 @@ <include layout="@layout/car_status_bar_header"/> <include layout="@layout/car_qs_footer"/> - <com.android.systemui.statusbar.car.UserGridView - android:id="@+id/user_grid" + <RelativeLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/user_switcher_container" + android:clipChildren="false" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginLeft="@dimen/car_margin" - android:layout_marginRight="@dimen/car_margin" /> + android:layout_height="@dimen/car_user_switcher_container_height" + android:layout_gravity="center_horizontal" > + + <com.android.systemui.statusbar.car.UserGridView + android:id="@+id/user_grid" + android:clipChildren="false" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginLeft="@dimen/car_margin" + android:layout_marginRight="@dimen/car_margin" + android:layout_marginBottom="@dimen/car_user_grid_margin_bottom" + android:layout_above="@id/user_switcher_page_indicator" /> + + <com.android.systemui.statusbar.car.PageIndicator + android:id="@+id/user_switcher_page_indicator" + android:layout_width="match_parent" + android:layout_height="@dimen/car_page_indicator_dot_diameter" + android:layout_marginBottom="@dimen/car_page_indicator_margin_bottom" + android:alpha="0" + android:layout_alignParentBottom="true" /> + + </RelativeLayout> + </LinearLayout> diff --git a/packages/SystemUI/res/values/dimens_car.xml b/packages/SystemUI/res/values/dimens_car.xml index 8853587dba47..f3c9f89bad41 100644 --- a/packages/SystemUI/res/values/dimens_car.xml +++ b/packages/SystemUI/res/values/dimens_car.xml @@ -18,20 +18,23 @@ <resources> <dimen name="car_margin">148dp</dimen> + <dimen name="car_fullscreen_user_pod_margin_image_top">24dp</dimen> <dimen name="car_fullscreen_user_pod_margin_name_top">24dp</dimen> - <dimen name="car_fullscreen_user_pod_margin_name_bottom">64dp</dimen> + <dimen name="car_fullscreen_user_pod_margin_name_bottom">20dp</dimen> <dimen name="car_fullscreen_user_pod_margin_between">24dp</dimen> <dimen name="car_fullscreen_user_pod_icon_text_size">96dp</dimen> <dimen name="car_fullscreen_user_pod_image_avatar_width">192dp</dimen> <dimen name="car_fullscreen_user_pod_image_avatar_height">192dp</dimen> <dimen name="car_fullscreen_user_pod_width">264dp</dimen> - <dimen name="car_fullscreen_user_pod_text_size">40sp</dimen> <!-- B1 --> + <dimen name="car_fullscreen_user_pod_height">356dp</dimen> + <dimen name="car_fullscreen_user_pod_name_text_size">40sp</dimen> <!-- B1 --> + <dimen name="car_fullscreen_user_pod_device_text_size">@dimen/car_body2_size</dimen> <dimen name="car_navigation_button_width">64dp</dimen> <dimen name="car_navigation_bar_width">760dp</dimen> <dimen name="car_page_indicator_dot_diameter">12dp</dimen> - <dimen name="car_page_indicator_margin_top">32dp</dimen> + <dimen name="car_page_indicator_margin_bottom">24dp</dimen> <dimen name="car_user_switcher_progress_bar_height">6dp</dimen> <dimen name="car_user_switcher_progress_bar_margin_top">@dimen/status_bar_height</dimen> @@ -47,8 +50,14 @@ <dimen name="car_qs_footer_padding_start">46dp</dimen> <dimen name="car_qs_footer_icon_width">56dp</dimen> <dimen name="car_qs_footer_icon_height">56dp</dimen> - <dimen name="car_qs_footer_user_switch_margin_right">46dp</dimen> + <dimen name="car_qs_footer_user_switch_icon_margin">5dp</dimen> + <dimen name="car_qs_footer_user_switch_icon_width">36dp</dimen> <dimen name="car_qs_footer_user_name_text_size">@dimen/car_body2_size</dimen> + <dimen name="car_user_switcher_container_height">420dp</dimen> + <!-- This must be the negative of car_user_switcher_container_height for the animation. --> + <dimen name="car_user_switcher_container_anim_height">-420dp</dimen> + <dimen name="car_user_grid_margin_bottom">28dp</dimen> + <dimen name="car_body2_size">26sp</dimen> </resources> diff --git a/packages/SystemUI/res/values/integers_car.xml b/packages/SystemUI/res/values/integers_car.xml index 320ee9f66c79..f84dd4bd5f27 100644 --- a/packages/SystemUI/res/values/integers_car.xml +++ b/packages/SystemUI/res/values/integers_car.xml @@ -19,4 +19,5 @@ <integer name="car_user_switcher_timeout_ms">15000</integer> <!-- This values less than ProgressBar.PROGRESS_ANIM_DURATION for a smooth animation. --> <integer name="car_user_switcher_anim_update_ms">60</integer> + <integer name="car_user_switcher_anim_cascade_delay_ms">27</integer> </resources> diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java index d80a33632f3e..9ff681555706 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java @@ -333,6 +333,7 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe */ private class KeyguardSliceButton extends Button { + private static final float SEPARATOR_HEIGHT = 0.7f; private final Paint mPaint; private boolean mHasDivider; @@ -369,7 +370,9 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe super.onDraw(canvas); if (mHasDivider) { final int lineX = getLayoutDirection() == LAYOUT_DIRECTION_RTL ? 0 : getWidth(); - canvas.drawLine(lineX, 0, lineX, getHeight(), mPaint); + final int height = (int) (getHeight() * SEPARATOR_HEIGHT); + final int startY = getHeight() / 2 - height / 2; + canvas.drawLine(lineX, startY, lineX, startY + height, mPaint); } } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java index 2873afbca8e9..2b656c220d63 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java @@ -171,15 +171,16 @@ public class KeyguardStatusView extends GridLayout { } private void onSliceContentChanged(boolean hasHeader) { - final float clockScale = hasHeader ? mSmallClockScale : 1; + final boolean smallClock = hasHeader || mPulsing; + final float clockScale = smallClock ? mSmallClockScale : 1; float translation = (mClockView.getHeight() - (mClockView.getHeight() * clockScale)) / 2f; - if (hasHeader) { + if (smallClock) { translation -= mWidgetPadding; } mClockView.setTranslationY(translation); mClockView.setScaleX(clockScale); mClockView.setScaleY(clockScale); - mClockSeparator.setVisibility(hasHeader ? VISIBLE : GONE); + mClockSeparator.setVisibility(hasHeader && !mPulsing ? VISIBLE : GONE); } @Override @@ -329,6 +330,8 @@ public class KeyguardStatusView extends GridLayout { public void setPulsing(boolean pulsing) { mPulsing = pulsing; + mKeyguardSlice.setVisibility(pulsing ? GONE : VISIBLE); + onSliceContentChanged(mKeyguardSlice.hasHeader()); updateDozeVisibleViews(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java index 142aab2626a6..23d3ebbbfe80 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java @@ -47,7 +47,7 @@ public class CarQSFooter extends RelativeLayout implements QSFooter, private MultiUserSwitch mMultiUserSwitch; private TextView mUserName; private ImageView mMultiUserAvatar; - private UserGridView mUserGridView; + private CarQSFragment.UserSwitchCallback mUserSwitchCallback; public CarQSFooter(Context context, AttributeSet attrs) { super(context, attrs); @@ -63,15 +63,15 @@ public class CarQSFooter extends RelativeLayout implements QSFooter, mUserInfoController = Dependency.get(UserInfoController.class); mMultiUserSwitch.setOnClickListener(v -> { - if (mUserGridView == null) { + if (mUserSwitchCallback == null) { Log.e(TAG, "CarQSFooter not properly set up; cannot display user switcher."); return; } - if (!mUserGridView.isShowing()) { - mUserGridView.show(); + if (!mUserSwitchCallback.isShowing()) { + mUserSwitchCallback.show(); } else { - mUserGridView.hide(); + mUserSwitchCallback.hide(); } }); @@ -102,8 +102,8 @@ public class CarQSFooter extends RelativeLayout implements QSFooter, } } - public void setUserGridView(UserGridView view) { - mUserGridView = view; + public void setUserSwitchCallback(CarQSFragment.UserSwitchCallback callback) { + mUserSwitchCallback = callback; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java index 13298d378845..0ee6d1fb6664 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java +++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java @@ -13,6 +13,12 @@ */ package com.android.systemui.qs.car; +import android.animation.Animator; +import android.animation.AnimatorInflater; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; import android.app.Fragment; import android.os.Bundle; import android.support.annotation.Nullable; @@ -26,18 +32,29 @@ import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.plugins.qs.QS; import com.android.systemui.qs.QSFooter; +import com.android.systemui.statusbar.car.PageIndicator; import com.android.systemui.statusbar.car.UserGridView; import com.android.systemui.statusbar.policy.UserSwitcherController; +import java.util.ArrayList; +import java.util.List; + /** * A quick settings fragment for the car. For auto, there is no row for quick settings or ability * to expand the quick settings panel. Instead, the only thing is that displayed is the * status bar, and a static row with access to the user switcher and settings. */ public class CarQSFragment extends Fragment implements QS { + private ViewGroup mPanel; private View mHeader; + private View mUserSwitcherContainer; private CarQSFooter mFooter; + private View mFooterUserName; + private View mFooterExpandIcon; private UserGridView mUserGridView; + private PageIndicator mPageIndicator; + private AnimatorSet mAnimatorSet; + private UserSwitchCallback mUserSwitchCallback; @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @@ -48,14 +65,26 @@ public class CarQSFragment extends Fragment implements QS { @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); + mPanel = (ViewGroup) view; mHeader = view.findViewById(R.id.header); mFooter = view.findViewById(R.id.qs_footer); + mFooterUserName = mFooter.findViewById(R.id.user_name); + mFooterExpandIcon = mFooter.findViewById(R.id.user_switch_expand_icon); + + mUserSwitcherContainer = view.findViewById(R.id.user_switcher_container); + + updateUserSwitcherHeight(0); mUserGridView = view.findViewById(R.id.user_grid); mUserGridView.init(null, Dependency.get(UserSwitcherController.class), - false /* showInitially */); + false /* overrideAlpha */); - mFooter.setUserGridView(mUserGridView); + mPageIndicator = view.findViewById(R.id.user_switcher_page_indicator); + mPageIndicator.setupWithViewPager(mUserGridView); + + mUserSwitchCallback = new UserSwitchCallback(); + mFooter.setUserSwitchCallback(mUserSwitchCallback); + mUserGridView.setUserSwitchCallback(mUserSwitchCallback); } @Override @@ -82,11 +111,13 @@ public class CarQSFragment extends Fragment implements QS { @Override public void setHeaderListening(boolean listening) { mFooter.setListening(listening); + mUserGridView.setListening(listening); } @Override public void setListening(boolean listening) { mFooter.setListening(listening); + mUserGridView.setListening(listening); } @Override @@ -171,4 +202,126 @@ public class CarQSFragment extends Fragment implements QS { public void setExpandClickListener(OnClickListener onClickListener) { // No ability to expand the quick settings. } + + public class UserSwitchCallback { + private boolean mShowing; + + public boolean isShowing() { + return mShowing; + } + + public void show() { + mShowing = true; + animateHeightChange(true /* opening */); + } + + public void hide() { + mShowing = false; + animateHeightChange(false /* opening */); + } + + public void resetShowing() { + if (mShowing) { + for (int i = 0; i < mUserGridView.getChildCount(); i++) { + ViewGroup podContainer = (ViewGroup) mUserGridView.getChildAt(i); + // Need to bring the last child to the front to maintain the order in the pod + // container. Why? ¯\_(ツ)_/¯ + if (podContainer.getChildCount() > 0) { + podContainer.getChildAt(podContainer.getChildCount() - 1).bringToFront(); + } + // The alpha values are default to 0, so if the pods have been refreshed, they + // need to be set to 1 when showing. + for (int j = 0; j < podContainer.getChildCount(); j++) { + podContainer.getChildAt(j).setAlpha(1f); + } + } + } + } + } + + private void updateUserSwitcherHeight(int height) { + ViewGroup.LayoutParams layoutParams = mUserSwitcherContainer.getLayoutParams(); + layoutParams.height = height; + mUserSwitcherContainer.requestLayout(); + } + + private void animateHeightChange(boolean opening) { + // Animation in progress; cancel it to avoid contention. + if (mAnimatorSet != null){ + mAnimatorSet.cancel(); + } + + List<Animator> allAnimators = new ArrayList<>(); + ValueAnimator heightAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(getContext(), + opening ? R.anim.car_user_switcher_open_animation + : R.anim.car_user_switcher_close_animation); + heightAnimator.addUpdateListener(valueAnimator -> { + updateUserSwitcherHeight((Integer) valueAnimator.getAnimatedValue()); + }); + allAnimators.add(heightAnimator); + + // The user grid contains pod containers that each contain a number of pods. Animate + // all pods to avoid any discrepancy/race conditions with possible changes during the + // animation. + int cascadeDelay = getResources().getInteger( + R.integer.car_user_switcher_anim_cascade_delay_ms); + for (int i = 0; i < mUserGridView.getChildCount(); i++) { + ViewGroup podContainer = (ViewGroup) mUserGridView.getChildAt(i); + for (int j = 0; j < podContainer.getChildCount(); j++) { + View pod = podContainer.getChildAt(j); + Animator podAnimator = AnimatorInflater.loadAnimator(getContext(), + opening ? R.anim.car_user_switcher_open_pod_animation + : R.anim.car_user_switcher_close_pod_animation); + // Add the cascading delay between pods + if (opening) { + podAnimator.setStartDelay(podAnimator.getStartDelay() + j * cascadeDelay); + } + podAnimator.setTarget(pod); + allAnimators.add(podAnimator); + } + } + + Animator nameAnimator = AnimatorInflater.loadAnimator(getContext(), + opening ? R.anim.car_user_switcher_open_name_animation + : R.anim.car_user_switcher_close_name_animation); + nameAnimator.setTarget(mFooterUserName); + allAnimators.add(nameAnimator); + + Animator iconAnimator = AnimatorInflater.loadAnimator(getContext(), + opening ? R.anim.car_user_switcher_open_icon_animation + : R.anim.car_user_switcher_close_icon_animation); + iconAnimator.setTarget(mFooterExpandIcon); + allAnimators.add(iconAnimator); + + Animator pageAnimator = AnimatorInflater.loadAnimator(getContext(), + opening ? R.anim.car_user_switcher_open_pages_animation + : R.anim.car_user_switcher_close_pages_animation); + pageAnimator.setTarget(mPageIndicator); + allAnimators.add(pageAnimator); + + mAnimatorSet = new AnimatorSet(); + mAnimatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mAnimatorSet = null; + } + }); + mAnimatorSet.playTogether(allAnimators.toArray(new Animator[0])); + + // Setup all values to the start values in the animations, since there are delays, but need + // to have all values start at the beginning. + setupInitialValues(mAnimatorSet); + + mAnimatorSet.start(); + } + + private void setupInitialValues(Animator anim) { + if (anim instanceof AnimatorSet) { + for (Animator a : ((AnimatorSet) anim).getChildAnimations()) { + setupInitialValues(a); + } + } else if (anim instanceof ObjectAnimator) { + ((ObjectAnimator) anim).setCurrentFraction(0.0f); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java index 172c62a99db2..3ec89138d1c0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java @@ -53,7 +53,7 @@ public class FullscreenUserSwitcher { mParent = containerStub.inflate(); mContainer = mParent.findViewById(R.id.container); mUserGridView = mContainer.findViewById(R.id.user_grid); - mUserGridView.init(statusBar, mUserSwitcherController, true /* showInitially */); + mUserGridView.init(statusBar, mUserSwitcherController, true /* overrideAlpha */); mUserGridView.setUserSelectionListener(record -> { if (!record.isCurrent) { toggleSwitchInProgress(true); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java index e551801ca434..1bd820db3f7c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java @@ -16,9 +16,6 @@ package com.android.systemui.statusbar.car; -import android.animation.Animator; -import android.animation.Animator.AnimatorListener; -import android.animation.ValueAnimator; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; @@ -29,62 +26,110 @@ import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; -import android.support.v4.view.animation.FastOutSlowInInterpolator; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.TextView; +import com.android.systemui.Dependency; import com.android.systemui.R; +import com.android.systemui.qs.car.CarQSFragment; import com.android.systemui.statusbar.phone.StatusBar; +import com.android.systemui.statusbar.policy.UserInfoController; import com.android.systemui.statusbar.policy.UserSwitcherController; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Vector; + /** * Displays a ViewPager with icons for the users in the system to allow switching between users. * One of the uses of this is for the lock screen in auto. */ -public class UserGridView extends ViewPager { - private static final int EXPAND_ANIMATION_TIME_MS = 200; - private static final int HIDE_ANIMATION_TIME_MS = 133; - +public class UserGridView extends ViewPager implements + UserInfoController.OnUserInfoChangedListener { private StatusBar mStatusBar; private UserSwitcherController mUserSwitcherController; private Adapter mAdapter; private UserSelectionListener mUserSelectionListener; - private ValueAnimator mHeightAnimator; - private int mTargetHeight; - private int mHeightChildren; - private boolean mShowing; + private UserInfoController mUserInfoController; + private Vector mUserContainers; + private int mContainerWidth; + private boolean mOverrideAlpha; + private CarQSFragment.UserSwitchCallback mUserSwitchCallback; public UserGridView(Context context, AttributeSet attrs) { super(context, attrs); } public void init(StatusBar statusBar, UserSwitcherController userSwitcherController, - boolean showInitially) { + boolean overrideAlpha) { mStatusBar = statusBar; mUserSwitcherController = userSwitcherController; mAdapter = new Adapter(mUserSwitcherController); - addOnLayoutChangeListener(mAdapter); - setAdapter(mAdapter); - mShowing = showInitially; + mUserInfoController = Dependency.get(UserInfoController.class); + mOverrideAlpha = overrideAlpha; + // Whenever the container width changes, the containers must be refreshed. Instead of + // doing an initial refreshContainers() to populate the containers, this listener will + // refresh them on layout change because that affects how the users are split into + // containers. Furthermore, at this point, the container width is unknown, so + // refreshContainers() cannot populate any containers. + addOnLayoutChangeListener( + (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { + int newWidth = Math.max(left - right, right - left); + if (mContainerWidth != newWidth) { + mContainerWidth = newWidth; + refreshContainers(); + } + }); } - public boolean isShowing() { - return mShowing; + private void refreshContainers() { + mUserContainers = new Vector(); + + Context context = getContext(); + LayoutInflater inflater = LayoutInflater.from(context); + + for (int i = 0; i < mAdapter.getCount(); i++) { + ViewGroup pods = (ViewGroup) inflater.inflate( + R.layout.car_fullscreen_user_pod_container, null); + + int iconsPerPage = mAdapter.getIconsPerPage(); + int limit = Math.min(mUserSwitcherController.getUsers().size(), (i + 1) * iconsPerPage); + for (int j = i * iconsPerPage; j < limit; j++) { + View v = mAdapter.makeUserPod(inflater, context, j, pods); + if (mOverrideAlpha) { + v.setAlpha(1f); + } + pods.addView(v); + // This is hacky, but the dividers on the pod container LinearLayout don't seem + // to work for whatever reason. Instead, set a right margin on the pod if it's not + // the right-most pod and there is more than one pod in the container. + if (i < limit - 1 && limit > 1) { + ViewGroup.MarginLayoutParams params = + (ViewGroup.MarginLayoutParams) v.getLayoutParams(); + params.setMargins(0, 0, getResources().getDimensionPixelSize( + R.dimen.car_fullscreen_user_pod_margin_between), 0); + v.setLayoutParams(params); + } + } + mUserContainers.add(pods); + } + + mAdapter = new Adapter(mUserSwitcherController); + setAdapter(mAdapter); } - public void show() { - mShowing = true; - animateHeightChange(getMeasuredHeight(), mHeightChildren); + @Override + public void onUserInfoChanged(String name, Drawable picture, String userAccount) { + refreshContainers(); } - public void hide() { - mShowing = false; - animateHeightChange(getMeasuredHeight(), 0); + public void setUserSwitchCallback(CarQSFragment.UserSwitchCallback callback) { + mUserSwitchCallback = callback; } public void onUserSwitched(int newUserId) { @@ -96,6 +141,14 @@ public class UserGridView extends ViewPager { mUserSelectionListener = userSelectionListener; } + public void setListening(boolean listening) { + if (listening) { + mUserInfoController.addCallback(this); + } else { + mUserInfoController.removeCallback(this); + } + } + void showOfflineAuthUi() { // TODO: Show keyguard UI in-place. mStatusBar.executeRunnableDismissingKeyguard(null, null, true, true, true); @@ -115,13 +168,6 @@ public class UserGridView extends ViewPager { height = Math.max(child.getMeasuredHeight(), height); } - mHeightChildren = height; - - // Override the height if it's not showing. - if (!mShowing) { - height = 0; - } - // Respect the AT_MOST request from parent. if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) { height = Math.min(MeasureSpec.getSize(heightMeasureSpec), height); @@ -132,72 +178,19 @@ public class UserGridView extends ViewPager { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } - private void animateHeightChange(int oldHeight, int newHeight) { - // If there is no change in height or an animation is already in progress towards the - // desired height, then there's no need to make any changes. - if (oldHeight == newHeight || newHeight == mTargetHeight) { - return; - } - - // Animation in progress is not going towards the new target, so cancel it. - if (mHeightAnimator != null){ - mHeightAnimator.cancel(); - } - - mTargetHeight = newHeight; - mHeightAnimator = ValueAnimator.ofInt(oldHeight, mTargetHeight); - mHeightAnimator.addUpdateListener(valueAnimator -> { - ViewGroup.LayoutParams layoutParams = getLayoutParams(); - layoutParams.height = (Integer) valueAnimator.getAnimatedValue(); - requestLayout(); - }); - mHeightAnimator.addListener(new AnimatorListener() { - @Override - public void onAnimationStart(Animator animator) {} - - @Override - public void onAnimationEnd(Animator animator) { - // ValueAnimator does not guarantee that the update listener will get an update - // to the final value, so here, the final value is set. Though the final calculated - // height (mTargetHeight) could be set, WRAP_CONTENT is more appropriate. - ViewGroup.LayoutParams layoutParams = getLayoutParams(); - layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT; - requestLayout(); - mHeightAnimator = null; - } - - @Override - public void onAnimationCancel(Animator animator) {} - - @Override - public void onAnimationRepeat(Animator animator) {} - }); - - mHeightAnimator.setInterpolator(new FastOutSlowInInterpolator()); - if (oldHeight < newHeight) { - // Expanding - mHeightAnimator.setDuration(EXPAND_ANIMATION_TIME_MS); - } else { - // Hiding - mHeightAnimator.setDuration(HIDE_ANIMATION_TIME_MS); - } - mHeightAnimator.start(); - } - /** * This is a ViewPager.PagerAdapter which deletegates the work to a * UserSwitcherController.BaseUserAdapter. Java doesn't support multiple inheritance so we have * to use composition instead to achieve the same goal since both the base classes are abstract * classes and not interfaces. */ - private final class Adapter extends PagerAdapter implements View.OnLayoutChangeListener { + private final class Adapter extends PagerAdapter { private final int mPodWidth; private final int mPodMarginBetween; private final int mPodImageAvatarWidth; private final int mPodImageAvatarHeight; private final WrappedBaseUserAdapter mUserAdapter; - private int mContainerWidth; public Adapter(UserSwitcherController controller) { super(); @@ -229,30 +222,20 @@ public class UserGridView extends ViewPager { } @Override - public Object instantiateItem(ViewGroup container, int position) { - Context context = getContext(); - LayoutInflater inflater = LayoutInflater.from(context); - - ViewGroup pods = (ViewGroup) inflater.inflate( - R.layout.car_fullscreen_user_pod_container, null); + public void finishUpdate(ViewGroup container) { + if (mUserSwitchCallback != null) { + mUserSwitchCallback.resetShowing(); + } + } - int iconsPerPage = getIconsPerPage(); - int limit = Math.min(mUserAdapter.getCount(), (position + 1) * iconsPerPage); - for (int i = position * iconsPerPage; i < limit; i++) { - View v = makeUserPod(inflater, context, i, pods); - pods.addView(v); - // This is hacky, but the dividers on the pod container LinearLayout don't seem - // to work for whatever reason. Instead, set a right margin on the pod if it's not - // the right-most pod and there is more than one pod in the container. - if (i < limit - 1 && limit > 1) { - LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( - LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); - params.setMargins(0, 0, mPodMarginBetween, 0); - v.setLayoutParams(params); - } + @Override + public Object instantiateItem(ViewGroup container, int position) { + if (position < mUserContainers.size()) { + container.addView((View) mUserContainers.get(position)); + return mUserContainers.get(position); + } else { + return null; } - container.addView(pods); - return pods; } /** @@ -353,17 +336,10 @@ public class UserGridView extends ViewPager { public boolean isViewFromObject(View view, Object object) { return view == object; } - - @Override - public void onLayoutChange(View v, int left, int top, int right, int bottom, - int oldLeft, int oldTop, int oldRight, int oldBottom) { - mContainerWidth = Math.max(left - right, right - left); - notifyDataSetChanged(); - } } private final class WrappedBaseUserAdapter extends UserSwitcherController.BaseUserAdapter { - private Adapter mContainer; + private final Adapter mContainer; public WrappedBaseUserAdapter(UserSwitcherController controller, Adapter container) { super(controller); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 0cc7f5dfbae1..66cb59e3d317 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -72,6 +72,7 @@ import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; import com.android.systemui.statusbar.stack.StackStateAnimator; +import java.util.Collection; import java.util.List; public class NotificationPanelView extends PanelView implements @@ -2621,8 +2622,10 @@ public class NotificationPanelView extends PanelView implements } } - public void setPulsing(boolean pulsing) { - mKeyguardStatusView.setPulsing(pulsing); + public void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> pulsing) { + mKeyguardStatusView.setPulsing(pulsing != null); + mNotificationStackScroller.setPulsing(pulsing, mKeyguardStatusView.getLocationOnScreen()[1] + + mKeyguardStatusView.getClockBottom()); } public void setAmbientIndicationBottomPadding(int ambientIndicationBottomPadding) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java index 6fc5bbdd5977..ee1d08872999 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java @@ -28,6 +28,7 @@ import android.graphics.Paint; import android.graphics.Rect; import android.os.Handler; import android.os.RemoteException; +import android.os.SystemProperties; import android.util.Log; import android.util.Slog; import android.view.Display; @@ -131,7 +132,7 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene new GestureDetector.SimpleOnGestureListener() { @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velX, float velY) { - if (mQuickScrubActive) { + if (!isQuickScrubEnabled() || mQuickScrubActive) { return false; } float velocityX = mIsRTL ? -velX : velX; @@ -196,12 +197,13 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene case MotionEvent.ACTION_DOWN: { int x = (int) event.getX(); int y = (int) event.getY(); - if (mHomeButtonRect.contains(x, y)) { + if (isQuickScrubEnabled() && mHomeButtonRect.contains(x, y)) { mTouchDownX = x; mTouchDownY = y; homeButton.setDelayTouchFeedback(true); mHandler.postDelayed(mLongPressRunnable, LONG_PRESS_DELAY_MS); } else { + homeButton.setDelayTouchFeedback(false); mTouchDownX = mTouchDownY = -1; } break; @@ -356,6 +358,10 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene } } + boolean isQuickScrubEnabled() { + return SystemProperties.getBoolean("persist.quickstep.scrub.enabled", false); + } + private void startQuickScrub() { if (!mQuickScrubActive) { mQuickScrubActive = true; 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 c30fb22630da..3b783c2a079a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -4620,8 +4620,7 @@ public class StatusBar extends SystemUI implements DemoMode, } private void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> pulsing) { - mStackScroller.setPulsing(pulsing); - mNotificationPanel.setPulsing(pulsing != null); + mNotificationPanel.setPulsing(pulsing); mVisualStabilityManager.setPulsing(pulsing != null); mIgnoreTouchWhilePulsing = false; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java index 443e760d88ae..af3d64be0fd0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -399,6 +399,7 @@ public class NotificationStackScrollLayout extends ViewGroup private final int mSeparatorWidth; private final int mSeparatorThickness; private final Rect mTmpRect = new Rect(); + private int mClockBottom; public NotificationStackScrollLayout(Context context) { this(context, null); @@ -510,7 +511,9 @@ public class NotificationStackScrollLayout extends ViewGroup final int darkTop = (int) (mRegularTopPadding + mSeparatorThickness / 2f); final int darkBottom = darkTop + mSeparatorThickness; - if (mAmbientState.isDark()) { + if (mAmbientState.hasPulsingNotifications()) { + // TODO draw divider between notification and shelf + } else if (mAmbientState.isDark()) { // Only draw divider on AOD if we actually have notifications if (mFirstVisibleBackgroundChild != null) { canvas.drawRect(darkLeft, darkTop, darkRight, darkBottom, mBackgroundPaint); @@ -684,7 +687,11 @@ public class NotificationStackScrollLayout extends ViewGroup } private void updateAlgorithmHeightAndPadding() { - mTopPadding = mAmbientState.isDark() ? mDarkTopPadding : mRegularTopPadding; + if (mPulsing != null) { + mTopPadding = mClockBottom; + } else { + mTopPadding = mAmbientState.isDark() ? mDarkTopPadding : mRegularTopPadding; + } mAmbientState.setLayoutHeight(getLayoutHeight()); updateAlgorithmLayoutMinHeight(); mAmbientState.setTopPadding(mTopPadding); @@ -4322,13 +4329,15 @@ public class NotificationStackScrollLayout extends ViewGroup return mIsExpanded; } - public void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> pulsing) { + public void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> pulsing, int clockBottom) { if (mPulsing == null && pulsing == null) { return; } mPulsing = pulsing; + mClockBottom = clockBottom; mAmbientState.setPulsing(pulsing); updateNotificationAnimationStates(); + updateAlgorithmHeightAndPadding(); updateContentHeight(); notifyHeightChangeListener(mShelf); requestChildrenUpdate(); diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/Android.mk b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/Android.mk new file mode 100644 index 000000000000..4f3a8b124a9b --- /dev/null +++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/Android.mk @@ -0,0 +1,13 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_RRO_THEME := DisplayCutoutEmulationNarrow +LOCAL_CERTIFICATE := platform + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res + +LOCAL_PACKAGE_NAME := DisplayCutoutEmulationNarrowOverlay + +include $(BUILD_RRO_PACKAGE) diff --git a/packages/overlays/DisplayCutoutEmulationOverlay/AndroidManifest.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/AndroidManifest.xml index dd4369094900..71ce6b433215 100644 --- a/packages/overlays/DisplayCutoutEmulationOverlay/AndroidManifest.xml +++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/AndroidManifest.xml @@ -1,7 +1,7 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.internal.display.cutout.emulation" - android:versionCode="1" - android:versionName="1.0"> + package="com.android.internal.display.cutout.emulation.narrow" + android:versionCode="1" + android:versionName="1.0"> <overlay android:targetPackage="android" android:priority="1"/> <application android:label="@string/display_cutout_emulation_overlay" android:hasCode="false"/> diff --git a/packages/overlays/DisplayCutoutEmulationOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml index 30e8b689883d..43bde88dabdd 100644 --- a/packages/overlays/DisplayCutoutEmulationOverlay/res/values/config.xml +++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml @@ -41,7 +41,7 @@ </string> <!-- Whether the display cutout region of the main built-in display should be forced to - black in software (to avoid aliasing or emulate a cutout that is not physically existent). + black in software (to avoid aliasing or emulate a cutout that is not physically existent). --> <bool name="config_fillMainBuiltInDisplayCutout">true</bool> diff --git a/packages/overlays/DisplayCutoutEmulationOverlay/res/values/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/strings.xml index 5d5c42590b21..49896773ac55 100644 --- a/packages/overlays/DisplayCutoutEmulationOverlay/res/values/strings.xml +++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/strings.xml @@ -18,7 +18,7 @@ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay">Display Cutout Emulation</string> + <string name="display_cutout_emulation_overlay">Narrow display cutout</string> </resources> diff --git a/packages/overlays/DisplayCutoutEmulationOverlay/Android.mk b/packages/overlays/DisplayCutoutEmulationTallOverlay/Android.mk index f4205ad68a1b..dac3878ae468 100644 --- a/packages/overlays/DisplayCutoutEmulationOverlay/Android.mk +++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/Android.mk @@ -1,13 +1,13 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) -LOCAL_RRO_THEME := DisplayCutoutEmulation +LOCAL_RRO_THEME := DisplayCutoutEmulationTall LOCAL_CERTIFICATE := platform LOCAL_SRC_FILES := $(call all-subdir-java-files) LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res -LOCAL_PACKAGE_NAME := DisplayCutoutEmulationOverlay +LOCAL_PACKAGE_NAME := DisplayCutoutEmulationTallOverlay include $(BUILD_RRO_PACKAGE) diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/AndroidManifest.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/AndroidManifest.xml new file mode 100644 index 000000000000..5a93cfb06c6d --- /dev/null +++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/AndroidManifest.xml @@ -0,0 +1,24 @@ +<!-- + ~ Copyright (C) 2018 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.internal.display.cutout.emulation.tall" + android:versionCode="1" + android:versionName="1.0"> + <overlay android:targetPackage="android" android:priority="1"/> + + <application android:label="@string/display_cutout_emulation_overlay" android:hasCode="false"/> +</manifest> diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml new file mode 100644 index 000000000000..9cf48d9e15a8 --- /dev/null +++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml @@ -0,0 +1,53 @@ +<!-- + ~ Copyright (C) 2018 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- The bounding path of the cutout region of the main built-in display. + Must either be empty if there is no cutout region, or a string that is parsable by + {@link android.util.PathParser}. + + The path is assumed to be specified in display coordinates with pixel units and in + the display's native orientation, with the origin of the coordinate system at the + center top of the display. + + To facilitate writing device-independent emulation overlays, the marker `@dp` can be + appended after the path string to interpret coordinates in dp instead of px units. + Note that a physical cutout should be configured in pixels for the best results. + --> + <string translatable="false" name="config_mainBuiltInDisplayCutout"> + M 0,0 + L -48, 0 + L -44.3940446283, 36.0595537175 + C -43.5582133885, 44.4178661152 -39.6, 48.0 -31.2, 48.0 + L 31.2, 48.0 + C 39.6, 48.0 43.5582133885, 44.4178661152 44.3940446283, 36.0595537175 + L 48, 0 + Z + @dp + </string> + + <!-- Whether the display cutout region of the main built-in display should be forced to + black in software (to avoid aliasing or emulate a cutout that is not physically existent). + --> + <bool name="config_fillMainBuiltInDisplayCutout">true</bool> + + <!-- Height of the status bar --> + <dimen name="status_bar_height">48dp</dimen> + +</resources> + + diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/strings.xml new file mode 100644 index 000000000000..6dcbbd923601 --- /dev/null +++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/strings.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2018 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <string name="display_cutout_emulation_overlay">Tall display cutout</string> + +</resources> + diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/Android.mk b/packages/overlays/DisplayCutoutEmulationWideOverlay/Android.mk new file mode 100644 index 000000000000..f4f250ca3a05 --- /dev/null +++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/Android.mk @@ -0,0 +1,13 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_RRO_THEME := DisplayCutoutEmulationWide +LOCAL_CERTIFICATE := platform + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res + +LOCAL_PACKAGE_NAME := DisplayCutoutEmulationWideOverlay + +include $(BUILD_RRO_PACKAGE) diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/AndroidManifest.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/AndroidManifest.xml new file mode 100644 index 000000000000..96bd06028611 --- /dev/null +++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/AndroidManifest.xml @@ -0,0 +1,24 @@ +<!-- + ~ Copyright (C) 2018 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.internal.display.cutout.emulation.wide" + android:versionCode="1" + android:versionName="1.0"> + <overlay android:targetPackage="android" android:priority="1"/> + + <application android:label="@string/display_cutout_emulation_overlay" android:hasCode="false"/> +</manifest> diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml new file mode 100644 index 000000000000..1ce41f07691d --- /dev/null +++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml @@ -0,0 +1,53 @@ +<!-- + ~ Copyright (C) 2018 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- The bounding path of the cutout region of the main built-in display. + Must either be empty if there is no cutout region, or a string that is parsable by + {@link android.util.PathParser}. + + The path is assumed to be specified in display coordinates with pixel units and in + the display's native orientation, with the origin of the coordinate system at the + center top of the display. + + To facilitate writing device-independent emulation overlays, the marker `@dp` can be + appended after the path string to interpret coordinates in dp instead of px units. + Note that a physical cutout should be configured in pixels for the best results. + --> + <string translatable="false" name="config_mainBuiltInDisplayCutout"> + M 0,0 + L -72, 0 + L -69.9940446283, 20.0595537175 + C -69.1582133885, 28.4178661152 -65.2, 32.0 -56.8, 32.0 + L 56.8, 32.0 + C 65.2, 32.0 69.1582133885, 28.4178661152 69.9940446283, 20.0595537175 + L 72, 0 + Z + @dp + </string> + + <!-- Whether the display cutout region of the main built-in display should be forced to + black in software (to avoid aliasing or emulate a cutout that is not physically existent). + --> + <bool name="config_fillMainBuiltInDisplayCutout">true</bool> + + <!-- Height of the status bar --> + <dimen name="status_bar_height">48dp</dimen> + +</resources> + + diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/strings.xml new file mode 100644 index 000000000000..f4b9f7ea7c37 --- /dev/null +++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/strings.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2018 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <string name="display_cutout_emulation_overlay">Wide display cutout</string> + +</resources> + diff --git a/services/core/Android.bp b/services/core/Android.bp index 3369458595a8..8da6d1e48ffe 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -32,6 +32,7 @@ java_library_static { static_libs: [ "time_zone_distro", "time_zone_distro_installer", + "android.hardware.authsecret-V1.0-java", "android.hardware.broadcastradio-V2.0-java", "android.hardware.health-V1.0-java", "android.hardware.health-V2.0-java", diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index c1f4b789e002..5030dce7cbf9 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -69,6 +69,7 @@ import android.net.NetworkRequest; import android.net.NetworkSpecifier; import android.net.NetworkState; import android.net.NetworkUtils; +import android.net.NetworkWatchlistManager; import android.net.Proxy; import android.net.ProxyInfo; import android.net.RouteInfo; @@ -5708,6 +5709,17 @@ public class ConnectivityService extends IConnectivityManager.Stub Settings.Global.NETWORK_AVOID_BAD_WIFI, null); } + @Override + public byte[] getNetworkWatchlistConfigHash() { + NetworkWatchlistManager nwm = mContext.getSystemService(NetworkWatchlistManager.class); + if (nwm == null) { + loge("Unable to get NetworkWatchlistManager"); + return null; + } + // Redirect it to network watchlist service to access watchlist file and calculate hash. + return nwm.getWatchlistConfigHash(); + } + @VisibleForTesting public NetworkMonitor createNetworkMonitor(Context context, Handler handler, NetworkAgentInfo nai, NetworkRequest defaultRequest) { diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index ef6bc437cb6c..24d493e3013e 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -571,6 +571,8 @@ public class IpSecService extends IIpSecService.Stub { mConfig = config; mSpi = spi; mSocket = socket; + + spi.setOwnedByTransform(); } public IpSecConfig getConfig() { @@ -651,16 +653,6 @@ public class IpSecService extends IIpSecService.Stub { /** always guarded by IpSecService#this */ @Override public void freeUnderlyingResources() { - if (mOwnedByTransform) { - Log.d(TAG, "Cannot release Spi " + mSpi + ": Currently locked by a Transform"); - // Because SPIs are "handed off" to transform, objects, they should never be - // freed from the SpiRecord once used in a transform. (They refer to the same SA, - // thus ownership and responsibility for freeing these resources passes to the - // Transform object). Thus, we should let the user free them without penalty once - // they are applied in a Transform object. - return; - } - try { mSrvConfig .getNetdInstance() @@ -694,6 +686,10 @@ public class IpSecService extends IIpSecService.Stub { mOwnedByTransform = true; } + public boolean getOwnedByTransform() { + return mOwnedByTransform; + } + @Override public void invalidate() throws RemoteException { getUserRecord().removeSpiRecord(mResourceId); @@ -1107,6 +1103,11 @@ public class IpSecService extends IIpSecService.Stub { // Retrieve SPI record; will throw IllegalArgumentException if not found SpiRecord s = userRecord.mSpiRecords.getResourceOrThrow(config.getSpiResourceId()); + // Check to ensure that SPI has not already been used. + if (s.getOwnedByTransform()) { + throw new IllegalStateException("SPI already in use; cannot be used in new Transforms"); + } + // If no remote address is supplied, then use one from the SPI. if (TextUtils.isEmpty(config.getDestinationAddress())) { config.setDestinationAddress(s.getDestinationAddress()); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index dc34567532bd..1eec982a0a9a 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -4711,7 +4711,8 @@ public class ActivityManagerService extends IActivityManager.Stub .setRequestCode(requestCode) .setStartFlags(startFlags) .setProfilerInfo(profilerInfo) - .setMayWait(bOptions, userId) + .setActivityOptions(bOptions) + .setMayWait(userId) .execute(); } @@ -4782,7 +4783,8 @@ public class ActivityManagerService extends IActivityManager.Stub .setResultWho(resultWho) .setRequestCode(requestCode) .setStartFlags(startFlags) - .setMayWait(bOptions, userId) + .setActivityOptions(bOptions) + .setMayWait(userId) .setIgnoreTargetSecurity(ignoreTargetSecurity) .execute(); } catch (SecurityException e) { @@ -4818,7 +4820,8 @@ public class ActivityManagerService extends IActivityManager.Stub .setResultWho(resultWho) .setRequestCode(requestCode) .setStartFlags(startFlags) - .setMayWait(bOptions, userId) + .setActivityOptions(bOptions) + .setMayWait(userId) .setProfilerInfo(profilerInfo) .setWaitResult(res) .execute(); @@ -4842,7 +4845,8 @@ public class ActivityManagerService extends IActivityManager.Stub .setRequestCode(requestCode) .setStartFlags(startFlags) .setGlobalConfiguration(config) - .setMayWait(bOptions, userId) + .setActivityOptions(bOptions) + .setMayWait(userId) .execute(); } @@ -4897,7 +4901,8 @@ public class ActivityManagerService extends IActivityManager.Stub .setVoiceInteractor(interactor) .setStartFlags(startFlags) .setProfilerInfo(profilerInfo) - .setMayWait(bOptions, userId) + .setActivityOptions(bOptions) + .setMayWait(userId) .execute(); } @@ -4912,7 +4917,8 @@ public class ActivityManagerService extends IActivityManager.Stub .setCallingUid(callingUid) .setCallingPackage(callingPackage) .setResolvedType(resolvedType) - .setMayWait(bOptions, userId) + .setActivityOptions(bOptions) + .setMayWait(userId) .execute(); } @@ -4927,6 +4933,7 @@ public class ActivityManagerService extends IActivityManager.Stub throw new SecurityException(msg); } + final SafeActivityOptions safeOptions = SafeActivityOptions.fromBundle(options); final int recentsUid = mRecentTasks.getRecentsComponentUid(); final ComponentName recentsComponent = mRecentTasks.getRecentsComponent(); final String recentsPackage = recentsComponent.getPackageName(); @@ -4957,7 +4964,8 @@ public class ActivityManagerService extends IActivityManager.Stub return mActivityStartController.obtainStarter(intent, "startRecentsActivity") .setCallingUid(recentsUid) .setCallingPackage(recentsPackage) - .setMayWait(activityOptions, userId) + .setActivityOptions(safeOptions) + .setMayWait(userId) .execute(); } } finally { @@ -5045,17 +5053,17 @@ public class ActivityManagerService extends IActivityManager.Stub if (intent != null && intent.hasFileDescriptors() == true) { throw new IllegalArgumentException("File descriptors passed in Intent"); } - ActivityOptions options = ActivityOptions.fromBundle(bOptions); + SafeActivityOptions options = SafeActivityOptions.fromBundle(bOptions); synchronized (this) { final ActivityRecord r = ActivityRecord.isInStackLocked(callingActivity); if (r == null) { - ActivityOptions.abort(options); + SafeActivityOptions.abort(options); return false; } if (r.app == null || r.app.thread == null) { // The caller is not running... d'oh! - ActivityOptions.abort(options); + SafeActivityOptions.abort(options); return false; } intent = new Intent(intent); @@ -5100,7 +5108,7 @@ public class ActivityManagerService extends IActivityManager.Stub if (aInfo == null) { // Nobody who is next! - ActivityOptions.abort(options); + SafeActivityOptions.abort(options); if (debug) Slog.d(TAG, "Next matching activity: nothing found"); return false; } @@ -5162,10 +5170,13 @@ public class ActivityManagerService extends IActivityManager.Stub enforceCallerIsRecentsOrHasPermission(START_TASKS_FROM_RECENTS, "startActivityFromRecents()"); + final int callingPid = Binder.getCallingPid(); + final int callingUid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); try { synchronized (this) { - return mStackSupervisor.startActivityFromRecents(taskId, bOptions); + return mStackSupervisor.startActivityFromRecents(callingPid, callingUid, taskId, + SafeActivityOptions.fromBundle(bOptions)); } } finally { Binder.restoreCallingIdentity(origId); @@ -5182,7 +5193,8 @@ public class ActivityManagerService extends IActivityManager.Stub userId, false, ALLOW_FULL_ONLY, reason, null); // TODO: Switch to user app stacks here. int ret = mActivityStartController.startActivities(caller, -1, callingPackage, - intents, resolvedTypes, resultTo, bOptions, userId, reason); + intents, resolvedTypes, resultTo, SafeActivityOptions.fromBundle(bOptions), userId, + reason); return ret; } @@ -7941,9 +7953,9 @@ public class ActivityManagerService extends IActivityManager.Stub flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT |PendingIntent.FLAG_UPDATE_CURRENT); - PendingIntentRecord.Key key = new PendingIntentRecord.Key( - type, packageName, activity, resultWho, - requestCode, intents, resolvedTypes, flags, bOptions, userId); + PendingIntentRecord.Key key = new PendingIntentRecord.Key(type, packageName, activity, + resultWho, requestCode, intents, resolvedTypes, flags, + SafeActivityOptions.fromBundle(bOptions), userId); WeakReference<PendingIntentRecord> ref; ref = mIntentSenderRecords.get(key); PendingIntentRecord rec = ref != null ? ref.get() : null; @@ -10434,9 +10446,13 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public void startInPlaceAnimationOnFrontMostApplication(Bundle opts) throws RemoteException { - final ActivityOptions activityOptions = ActivityOptions.fromBundle(opts); - if (activityOptions.getAnimationType() != ActivityOptions.ANIM_CUSTOM_IN_PLACE || - activityOptions.getCustomInPlaceResId() == 0) { + final SafeActivityOptions safeOptions = SafeActivityOptions.fromBundle(opts); + final ActivityOptions activityOptions = safeOptions != null + ? safeOptions.getOptions(mStackSupervisor) + : null; + if (activityOptions == null + || activityOptions.getAnimationType() != ActivityOptions.ANIM_CUSTOM_IN_PLACE + || activityOptions.getCustomInPlaceResId() == 0) { throw new IllegalArgumentException("Expected in-place ActivityOption " + "with valid animation"); } @@ -10539,16 +10555,17 @@ public class ActivityManagerService extends IActivityManager.Stub if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToFront: moving taskId=" + taskId); synchronized(this) { - moveTaskToFrontLocked(taskId, flags, bOptions, false /* fromRecents */); + moveTaskToFrontLocked(taskId, flags, SafeActivityOptions.fromBundle(bOptions), + false /* fromRecents */); } } - void moveTaskToFrontLocked(int taskId, int flags, Bundle bOptions, boolean fromRecents) { - ActivityOptions options = ActivityOptions.fromBundle(bOptions); + void moveTaskToFrontLocked(int taskId, int flags, SafeActivityOptions options, + boolean fromRecents) { if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(), Binder.getCallingUid(), -1, -1, "Task to front")) { - ActivityOptions.abort(options); + SafeActivityOptions.abort(options); return; } final long origId = Binder.clearCallingIdentity(); @@ -10562,7 +10579,10 @@ public class ActivityManagerService extends IActivityManager.Stub Slog.e(TAG, "moveTaskToFront: Attempt to violate Lock Task Mode"); return; } - mStackSupervisor.findTaskToMoveToFront(task, flags, options, "moveTaskToFront", + ActivityOptions realOptions = options != null + ? options.getOptions(mStackSupervisor) + : null; + mStackSupervisor.findTaskToMoveToFront(task, flags, realOptions, "moveTaskToFront", false /* forceNonResizable */); final ActivityRecord topActivity = task.getTopActivity(); @@ -10576,7 +10596,7 @@ public class ActivityManagerService extends IActivityManager.Stub } finally { Binder.restoreCallingIdentity(origId); } - ActivityOptions.abort(options); + SafeActivityOptions.abort(options); } /** @@ -13534,6 +13554,7 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public boolean convertToTranslucent(IBinder token, Bundle options) { + SafeActivityOptions safeOptions = SafeActivityOptions.fromBundle(options); final long origId = Binder.clearCallingIdentity(); try { synchronized (this) { @@ -13545,7 +13566,7 @@ public class ActivityManagerService extends IActivityManager.Stub int index = task.mActivities.lastIndexOf(r); if (index > 0) { ActivityRecord under = task.mActivities.get(index - 1); - under.returningOptions = ActivityOptions.fromBundle(options); + under.returningOptions = safeOptions.getOptions(r); } final boolean translucentChanged = r.changeWindowTranslucency(false); if (translucentChanged) { @@ -24909,7 +24930,8 @@ public class ActivityManagerService extends IActivityManager.Stub synchronized (ActivityManagerService.this) { return mActivityStartController.startActivitiesInPackage(packageUid, packageName, - intents, resolvedTypes, /*resultTo*/ null, bOptions, userId); + intents, resolvedTypes, null /* resultTo */, + SafeActivityOptions.fromBundle(bOptions), userId); } } diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index eb14bbda4c4b..bfb563fd93a8 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -1591,7 +1591,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D boolean checkStartAnyActivityPermission(Intent intent, ActivityInfo aInfo, String resultWho, int requestCode, int callingPid, int callingUid, String callingPackage, boolean ignoreTargetSecurity, ProcessRecord callerApp, - ActivityRecord resultRecord, ActivityStack resultStack, ActivityOptions options) { + ActivityRecord resultRecord, ActivityStack resultStack) { final int startAnyPerm = mService.checkPermission(START_ANY_ACTIVITY, callingPid, callingUid); if (startAnyPerm == PERMISSION_GRANTED) { @@ -1645,57 +1645,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D Slog.w(TAG, message); return false; } - if (options != null) { - // If a launch task id is specified, then ensure that the caller is the recents - // component or has the START_TASKS_FROM_RECENTS permission - if (options.getLaunchTaskId() != INVALID_TASK_ID - && !mRecentTasks.isCallerRecents(callingUid)) { - final int startInTaskPerm = mService.checkPermission(START_TASKS_FROM_RECENTS, - callingPid, callingUid); - if (startInTaskPerm == PERMISSION_DENIED) { - final String msg = "Permission Denial: starting " + intent.toString() - + " from " + callerApp + " (pid=" + callingPid - + ", uid=" + callingUid + ") with launchTaskId=" - + options.getLaunchTaskId(); - Slog.w(TAG, msg); - throw new SecurityException(msg); - } - } - // Check if someone tries to launch an activity on a private display with a different - // owner. - final int launchDisplayId = options.getLaunchDisplayId(); - if (launchDisplayId != INVALID_DISPLAY && !isCallerAllowedToLaunchOnDisplay(callingPid, - callingUid, launchDisplayId, aInfo)) { - final String msg = "Permission Denial: starting " + intent.toString() - + " from " + callerApp + " (pid=" + callingPid - + ", uid=" + callingUid + ") with launchDisplayId=" - + launchDisplayId; - Slog.w(TAG, msg); - throw new SecurityException(msg); - } - // Check if someone tries to launch an unwhitelisted activity into LockTask mode. - final boolean lockTaskMode = options.getLockTaskMode(); - if (lockTaskMode && !mService.mLockTaskController.isPackageWhitelisted( - UserHandle.getUserId(callingUid), aInfo.packageName)) { - final String msg = "Permission Denial: starting " + intent.toString() - + " from " + callerApp + " (pid=" + callingPid - + ", uid=" + callingUid + ") with lockTaskMode=true"; - Slog.w(TAG, msg); - throw new SecurityException(msg); - } - - // Check permission for remote animations - final RemoteAnimationAdapter adapter = options.getRemoteAnimationAdapter(); - if (adapter != null && mService.checkPermission( - CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS, callingPid, callingUid) - != PERMISSION_GRANTED) { - final String msg = "Permission Denial: starting " + intent.toString() - + " from " + callerApp + " (pid=" + callingPid - + ", uid=" + callingUid + ") with remoteAnimationAdapter"; - Slog.w(TAG, msg); - throw new SecurityException(msg); - } - } return true; } @@ -2166,8 +2115,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } } - void findTaskToMoveToFront(TaskRecord task, int flags, ActivityOptions options, - String reason, boolean forceNonResizeable) { + void findTaskToMoveToFront(TaskRecord task, int flags, ActivityOptions options, String reason, + boolean forceNonResizeable) { final ActivityStack currentStack = task.getStack(); if (currentStack == null) { Slog.e(TAG, "findTaskToMoveToFront: can't move task=" @@ -4546,16 +4495,17 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D task.setTaskDockedResizing(true); } - int startActivityFromRecents(int taskId, Bundle bOptions) { + int startActivityFromRecents(int callingPid, int callingUid, int taskId, + SafeActivityOptions options) { final TaskRecord task; - final int callingUid; final String callingPackage; final Intent intent; final int userId; int activityType = ACTIVITY_TYPE_UNDEFINED; int windowingMode = WINDOWING_MODE_UNDEFINED; - final ActivityOptions activityOptions = (bOptions != null) - ? new ActivityOptions(bOptions) : null; + final ActivityOptions activityOptions = options != null + ? options.getOptions(this) + : null; if (activityOptions != null) { activityType = activityOptions.getLaunchActivityType(); windowingMode = activityOptions.getLaunchWindowingMode(); @@ -4603,7 +4553,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D sendPowerHintForLaunchStartIfNeeded(true /* forceSend */, targetActivity); mActivityMetricsLogger.notifyActivityLaunching(); try { - mService.moveTaskToFrontLocked(task.taskId, 0, bOptions, + mService.moveTaskToFrontLocked(task.taskId, 0, options, true /* fromRecents */); } finally { mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT, @@ -4622,13 +4572,13 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D task.getStack()); return ActivityManager.START_TASK_TO_FRONT; } - callingUid = task.mCallingUid; callingPackage = task.mCallingPackage; intent = task.intent; intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY); userId = task.userId; - int result = mService.getActivityStartController().startActivityInPackage(callingUid, - callingPackage, intent, null, null, null, 0, 0, bOptions, userId, task, + int result = mService.getActivityStartController().startActivityInPackage( + task.mCallingUid, callingPid, callingUid, callingPackage, intent, null, null, + null, 0, 0, options, userId, task, "startActivityFromRecents"); if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { setResizingDuringAnimation(task); diff --git a/services/core/java/com/android/server/am/ActivityStartController.java b/services/core/java/com/android/server/am/ActivityStartController.java index aed49e0037e1..f9932b20fb5b 100644 --- a/services/core/java/com/android/server/am/ActivityStartController.java +++ b/services/core/java/com/android/server/am/ActivityStartController.java @@ -220,43 +220,44 @@ public class ActivityStartController { } } - final int startActivityInPackage(int uid, String callingPackage, - Intent intent, String resolvedType, IBinder resultTo, - String resultWho, int requestCode, int startFlags, Bundle bOptions, int userId, - TaskRecord inTask, String reason) { + final int startActivityInPackage(int uid, int realCallingUid, int realCallingPid, + String callingPackage, Intent intent, String resolvedType, IBinder resultTo, + String resultWho, int requestCode, int startFlags, SafeActivityOptions options, + int userId, TaskRecord inTask, String reason) { - userId = mService.mUserController.handleIncomingUser(Binder.getCallingPid(), - Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, "startActivityInPackage", - null); + userId = mService.mUserController.handleIncomingUser(realCallingPid, realCallingUid, userId, + false, ALLOW_FULL_ONLY, "startActivityInPackage", null); // TODO: Switch to user app stacks here. return obtainStarter(intent, reason) .setCallingUid(uid) + .setRealCallingPid(realCallingPid) + .setRealCallingUid(realCallingUid) .setCallingPackage(callingPackage) .setResolvedType(resolvedType) .setResultTo(resultTo) .setResultWho(resultWho) .setRequestCode(requestCode) .setStartFlags(startFlags) - .setMayWait(bOptions, userId) + .setActivityOptions(options) + .setMayWait(userId) .setInTask(inTask) .execute(); } final int startActivitiesInPackage(int uid, String callingPackage, Intent[] intents, - String[] resolvedTypes, IBinder resultTo, Bundle bOptions, int userId) { + String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId) { final String reason = "startActivityInPackage"; userId = mService.mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, reason, null); // TODO: Switch to user app stacks here. - int ret = startActivities(null, uid, callingPackage, intents, resolvedTypes, resultTo, - bOptions, userId, reason); - return ret; + return startActivities(null, uid, callingPackage, intents, resolvedTypes, resultTo, options, + userId, reason); } int startActivities(IApplicationThread caller, int callingUid, String callingPackage, - Intent[] intents, String[] resolvedTypes, IBinder resultTo, Bundle bOptions, int userId, - String reason) { + Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, + int userId, String reason) { if (intents == null) { throw new NullPointerException("intents is null"); } @@ -312,9 +313,9 @@ public class ActivityStartController { "FLAG_CANT_SAVE_STATE not supported here"); } - ActivityOptions options = ActivityOptions.fromBundle( - i == intents.length - 1 ? bOptions : null); - + final SafeActivityOptions checkedOptions = i == intents.length - 1 + ? options + : null; final int res = obtainStarter(intent, reason) .setCaller(caller) .setResolvedType(resolvedTypes[i]) @@ -326,7 +327,7 @@ public class ActivityStartController { .setCallingPackage(callingPackage) .setRealCallingPid(realCallingPid) .setRealCallingUid(realCallingUid) - .setActivityOptions(options) + .setActivityOptions(checkedOptions) .setComponentSpecified(componentSpecified) .setOutActivity(outActivity) .execute(); diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index 3a13155d88e1..8595aa394800 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -74,6 +74,7 @@ import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT; import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT; import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.IApplicationThread; @@ -298,7 +299,7 @@ class ActivityStarter { int realCallingPid; int realCallingUid; int startFlags; - ActivityOptions activityOptions; + SafeActivityOptions activityOptions; boolean ignoreTargetSecurity; boolean componentSpecified; ActivityRecord[] outActivity; @@ -306,13 +307,12 @@ class ActivityStarter { String reason; ProfilerInfo profilerInfo; Configuration globalConfig; - Bundle waitOptions; int userId; WaitResult waitResult; /** * Indicates that we should wait for the result of the start request. This flag is set when - * {@link ActivityStarter#setMayWait(Bundle, int)} is called. + * {@link ActivityStarter#setMayWait(int)} is called. * {@see ActivityStarter#startActivityMayWait}. */ boolean mayWait; @@ -353,7 +353,6 @@ class ActivityStarter { reason = null; profilerInfo = null; globalConfig = null; - waitOptions = null; userId = 0; waitResult = null; mayWait = false; @@ -388,7 +387,6 @@ class ActivityStarter { reason = request.reason; profilerInfo = request.profilerInfo; globalConfig = request.globalConfig; - waitOptions = request.waitOptions; userId = request.userId; waitResult = request.waitResult; mayWait = request.mayWait; @@ -473,7 +471,7 @@ class ActivityStarter { mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo, mRequest.resultWho, mRequest.requestCode, mRequest.startFlags, mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig, - mRequest.waitOptions, mRequest.ignoreTargetSecurity, mRequest.userId, + mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId, mRequest.inTask, mRequest.reason); } else { return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent, @@ -513,7 +511,7 @@ class ActivityStarter { IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid, String callingPackage, int realCallingPid, int realCallingUid, int startFlags, - ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified, + SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, TaskRecord inTask, String reason) { if (TextUtils.isEmpty(reason)) { @@ -555,8 +553,9 @@ class ActivityStarter { IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid, String callingPackage, int realCallingPid, int realCallingUid, int startFlags, - ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified, - ActivityRecord[] outActivity, TaskRecord inTask) { + SafeActivityOptions options, + boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, + TaskRecord inTask) { int err = ActivityManager.START_SUCCESS; // Pull the optional Ephemeral Installer-only bundle out of the options early. final Bundle verificationBundle @@ -603,7 +602,7 @@ class ActivityStarter { // Transfer the result target from the source activity to the new // one being started, including any failures. if (requestCode >= 0) { - ActivityOptions.abort(options); + SafeActivityOptions.abort(options); return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT; } resultRecord = sourceRecord.resultTo; @@ -691,16 +690,20 @@ class ActivityStarter { resultStack.sendActivityResultLocked( -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null); } - ActivityOptions.abort(options); + SafeActivityOptions.abort(options); return err; } boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho, - requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp, - resultRecord, resultStack, options); + requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, + callerApp, resultRecord, resultStack); abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid, callingPid, resolvedType, aInfo.applicationInfo); + // Merge the two options bundles, while realCallerOptions takes precedence. + ActivityOptions checkedOptions = options != null + ? options.getOptions(intent, aInfo, callerApp, mSupervisor) + : null; if (mService.mController != null) { try { // The Intent we give to the watcher has the extra data @@ -715,7 +718,7 @@ class ActivityStarter { mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage); if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, - callingUid, options)) { + callingUid, checkedOptions)) { // activity start was intercepted, e.g. because the target user is currently in quiet // mode (turn off work) or the target application is suspended intent = mInterceptor.mIntent; @@ -725,7 +728,7 @@ class ActivityStarter { inTask = mInterceptor.mInTask; callingPid = mInterceptor.mCallingPid; callingUid = mInterceptor.mCallingUid; - options = mInterceptor.mActivityOptions; + checkedOptions = mInterceptor.mActivityOptions; } if (abort) { @@ -735,7 +738,7 @@ class ActivityStarter { } // We pretend to the caller that it was really started, but // they will just get a cancel result. - ActivityOptions.abort(options); + ActivityOptions.abort(checkedOptions); return START_ABORTED; } @@ -796,7 +799,7 @@ class ActivityStarter { ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid, callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null, - mSupervisor, options, sourceRecord); + mSupervisor, checkedOptions, sourceRecord); if (outActivity != null) { outActivity[0] = r; } @@ -808,13 +811,16 @@ class ActivityStarter { } final ActivityStack stack = mSupervisor.mFocusedStack; + + // If we are starting an activity that is not from the same uid as the currently resumed + // one, check whether app switches are allowed. if (voiceSession == null && (stack.mResumedActivity == null - || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) { + || stack.mResumedActivity.info.applicationInfo.uid != realCallingUid)) { if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, realCallingPid, realCallingUid, "Activity start")) { mController.addPendingActivityLaunch(new PendingActivityLaunch(r, sourceRecord, startFlags, stack, callerApp)); - ActivityOptions.abort(options); + ActivityOptions.abort(checkedOptions); return ActivityManager.START_SWITCHES_CANCELED; } } @@ -833,9 +839,10 @@ class ActivityStarter { mController.doPendingActivityLaunches(false); return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, - true /* doResume */, options, inTask, outActivity); + true /* doResume */, checkedOptions, inTask, outActivity); } + /** * Creates a launch intent for the given auxiliary resolution data. */ @@ -900,8 +907,8 @@ class ActivityStarter { IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, WaitResult outResult, - Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId, - TaskRecord inTask, String reason) { + Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity, + int userId, TaskRecord inTask, String reason) { // Refuse possible leaked file descriptors if (intent != null && intent.hasFileDescriptors()) { throw new IllegalArgumentException("File descriptors passed in Intent"); @@ -953,7 +960,6 @@ class ActivityStarter { // Collect information about the target of the Intent. ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo); - ActivityOptions options = ActivityOptions.fromBundle(bOptions); synchronized (mService) { final int realCallingPid = Binder.getCallingPid(); final int realCallingUid = Binder.getCallingUid(); @@ -993,7 +999,7 @@ class ActivityStarter { Slog.w(TAG, "Unable to find app for caller " + caller + " (pid=" + callingPid + ") when starting: " + intent.toString()); - ActivityOptions.abort(options); + SafeActivityOptions.abort(options); return ActivityManager.START_PERMISSION_DENIED; } } @@ -1039,12 +1045,10 @@ class ActivityStarter { } final ActivityRecord[] outRecord = new ActivityRecord[1]; - int res = startActivity(caller, intent, ephemeralIntent, resolvedType, - aInfo, rInfo, voiceSession, voiceInteractor, - resultTo, resultWho, requestCode, callingPid, - callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, - options, ignoreTargetSecurity, componentSpecified, outRecord, inTask, - reason); + int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo, + voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid, + callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options, + ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason); Binder.restoreCallingIdentity(origId); @@ -1248,7 +1252,7 @@ class ActivityStarter { outActivity[0] = reusedActivity; } - return START_TASK_TO_FRONT; + return START_DELIVERED_TO_TOP; } } @@ -2447,11 +2451,15 @@ class ActivityStarter { return this; } - ActivityStarter setActivityOptions(ActivityOptions options) { + ActivityStarter setActivityOptions(SafeActivityOptions options) { mRequest.activityOptions = options; return this; } + ActivityStarter setActivityOptions(Bundle bOptions) { + return setActivityOptions(SafeActivityOptions.fromBundle(bOptions)); + } + ActivityStarter setIgnoreTargetSecurity(boolean ignoreTargetSecurity) { mRequest.ignoreTargetSecurity = ignoreTargetSecurity; return this; @@ -2487,19 +2495,13 @@ class ActivityStarter { return this; } - ActivityStarter setWaitOptions(Bundle options) { - mRequest.waitOptions = options; - return this; - } - ActivityStarter setUserId(int userId) { mRequest.userId = userId; return this; } - ActivityStarter setMayWait(Bundle options, int userId) { + ActivityStarter setMayWait(int userId) { mRequest.mayWait = true; - mRequest.waitOptions = options; mRequest.userId = userId; return this; diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java index 26d65bc7414c..0da7e0ec2f6d 100644 --- a/services/core/java/com/android/server/am/AppErrors.java +++ b/services/core/java/com/android/server/am/AppErrors.java @@ -408,9 +408,11 @@ class AppErrors { final Set<String> cats = task.intent.getCategories(); if (cats != null && cats.contains(Intent.CATEGORY_LAUNCHER)) { mService.getActivityStartController().startActivityInPackage( - task.mCallingUid, task.mCallingPackage, task.intent, null, null, - null, 0, 0, ActivityOptions.makeBasic().toBundle(), task.userId, - null, "AppErrors"); + task.mCallingUid, callingPid, callingUid, task.mCallingPackage, + task.intent, null, null, null, 0, 0, + new SafeActivityOptions(ActivityOptions.makeBasic()), + task.userId, null, + "AppErrors"); } } } diff --git a/services/core/java/com/android/server/am/AppTaskImpl.java b/services/core/java/com/android/server/am/AppTaskImpl.java index f821f6bdb925..5f5a504bb014 100644 --- a/services/core/java/com/android/server/am/AppTaskImpl.java +++ b/services/core/java/com/android/server/am/AppTaskImpl.java @@ -20,6 +20,7 @@ import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS; import android.app.ActivityManager; +import android.app.ActivityOptions; import android.app.IAppTask; import android.app.IApplicationThread; import android.content.Intent; @@ -93,10 +94,13 @@ class AppTaskImpl extends IAppTask.Stub { public void moveToFront() { checkCaller(); // Will bring task to front if it already has a root activity. + final int callingPid = Binder.getCallingPid(); + final int callingUid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); try { synchronized (this) { - mService.mStackSupervisor.startActivityFromRecents(mTaskId, null); + mService.mStackSupervisor.startActivityFromRecents(callingPid, callingUid, mTaskId, + null); } } finally { Binder.restoreCallingIdentity(origId); @@ -127,7 +131,8 @@ class AppTaskImpl extends IAppTask.Stub { .setCaller(appThread) .setCallingPackage(callingPackage) .setResolvedType(resolvedType) - .setMayWait(bOptions, callingUser) + .setActivityOptions(bOptions) + .setMayWait(callingUser) .setInTask(tr) .execute(); } diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java index c26e7703a1ca..8e9d85d60479 100644 --- a/services/core/java/com/android/server/am/PendingIntentRecord.java +++ b/services/core/java/com/android/server/am/PendingIntentRecord.java @@ -16,10 +16,12 @@ package com.android.server.am; +import static android.app.ActivityManager.START_SUCCESS; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; import android.app.ActivityManager; +import android.app.ActivityOptions; import android.content.IIntentSender; import android.content.IIntentReceiver; import android.app.PendingIntent; @@ -65,7 +67,7 @@ final class PendingIntentRecord extends IIntentSender.Stub { final int requestCode; final Intent requestIntent; final String requestResolvedType; - final Bundle options; + final SafeActivityOptions options; Intent[] allIntents; String[] allResolvedTypes; final int flags; @@ -75,7 +77,7 @@ final class PendingIntentRecord extends IIntentSender.Stub { private static final int ODD_PRIME_NUMBER = 37; Key(int _t, String _p, ActivityRecord _a, String _w, - int _r, Intent[] _i, String[] _it, int _f, Bundle _o, int _userId) { + int _r, Intent[] _i, String[] _it, int _f, SafeActivityOptions _o, int _userId) { type = _t; packageName = _p; activity = _a; @@ -310,17 +312,16 @@ final class PendingIntentRecord extends IIntentSender.Stub { if (userId == UserHandle.USER_CURRENT) { userId = owner.mUserController.getCurrentOrTargetUserId(); } - int res = 0; + int res = START_SUCCESS; switch (key.type) { case ActivityManager.INTENT_SENDER_ACTIVITY: - if (options == null) { - options = key.options; - } else if (key.options != null) { - Bundle opts = new Bundle(key.options); - opts.putAll(options); - options = opts; - } try { + SafeActivityOptions mergedOptions = key.options; + if (mergedOptions == null) { + mergedOptions = SafeActivityOptions.fromBundle(options); + } else { + mergedOptions.setCallerOptions(ActivityOptions.fromBundle(options)); + } if (key.allIntents != null && key.allIntents.length > 1) { Intent[] allIntents = new Intent[key.allIntents.length]; String[] allResolvedTypes = new String[key.allIntents.length]; @@ -332,14 +333,14 @@ final class PendingIntentRecord extends IIntentSender.Stub { } allIntents[allIntents.length-1] = finalIntent; allResolvedTypes[allResolvedTypes.length-1] = resolvedType; - owner.getActivityStartController().startActivitiesInPackage(uid, - key.packageName, allIntents, allResolvedTypes, resultTo, - options, userId); + res = owner.getActivityStartController().startActivitiesInPackage( + uid, key.packageName, allIntents, allResolvedTypes, + resultTo, mergedOptions, userId); } else { - owner.getActivityStartController().startActivityInPackage(uid, - key.packageName, finalIntent, resolvedType, resultTo, - resultWho, requestCode, 0, options, userId, null, - "PendingIntentRecord"); + res = owner.getActivityStartController().startActivityInPackage(uid, + callingPid, callingUid, key.packageName, finalIntent, + resolvedType, resultTo, resultWho, requestCode, 0, + mergedOptions, userId, null, "PendingIntentRecord"); } } catch (RuntimeException e) { Slog.w(TAG, "Unable to send startActivity intent", e); diff --git a/services/core/java/com/android/server/am/SafeActivityOptions.java b/services/core/java/com/android/server/am/SafeActivityOptions.java new file mode 100644 index 000000000000..d08111ec0aa5 --- /dev/null +++ b/services/core/java/com/android/server/am/SafeActivityOptions.java @@ -0,0 +1,232 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.server.am; + +import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS; +import static android.Manifest.permission.START_TASKS_FROM_RECENTS; +import static android.content.pm.PackageManager.PERMISSION_DENIED; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static android.view.Display.INVALID_DISPLAY; +import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; +import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.server.am.TaskRecord.INVALID_TASK_ID; + +import android.annotation.Nullable; +import android.app.ActivityOptions; +import android.app.PendingIntent; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.os.Binder; +import android.os.Bundle; +import android.os.UserHandle; +import android.util.Slog; +import android.view.RemoteAnimationAdapter; + +import com.android.internal.annotations.VisibleForTesting; + +/** + * Wraps {@link ActivityOptions}, records binder identity, and checks permission when retrieving + * the inner options. Also supports having two set of options: Once from the original caller, and + * once from the caller that is overriding it, which happens when sending a {@link PendingIntent}. + */ +class SafeActivityOptions { + + private static final String TAG = TAG_WITH_CLASS_NAME ? "SafeActivityOptions" : TAG_AM; + + private final int mOriginalCallingPid; + private final int mOriginalCallingUid; + private int mRealCallingPid; + private int mRealCallingUid; + private final @Nullable ActivityOptions mOriginalOptions; + private @Nullable ActivityOptions mCallerOptions; + + /** + * Constructs a new instance from a bundle and records {@link Binder#getCallingPid}/ + * {@link Binder#getCallingUid}. Thus, calling identity MUST NOT be cleared when constructing + * this object. + * + * @param bOptions The {@link ActivityOptions} as {@link Bundle}. + */ + static SafeActivityOptions fromBundle(Bundle bOptions) { + return bOptions != null + ? new SafeActivityOptions(ActivityOptions.fromBundle(bOptions)) + : null; + } + + /** + * Constructs a new instance and records {@link Binder#getCallingPid}/ + * {@link Binder#getCallingUid}. Thus, calling identity MUST NOT be cleared when constructing + * this object. + * + * @param options The options to wrap. + */ + SafeActivityOptions(@Nullable ActivityOptions options) { + mOriginalCallingPid = Binder.getCallingPid(); + mOriginalCallingUid = Binder.getCallingUid(); + mOriginalOptions = options; + } + + /** + * Overrides options with options from a caller and records {@link Binder#getCallingPid}/ + * {@link Binder#getCallingUid}. Thus, calling identity MUST NOT be cleared when calling this + * method. + */ + void setCallerOptions(@Nullable ActivityOptions options) { + mRealCallingPid = Binder.getCallingPid(); + mRealCallingUid = Binder.getCallingUid(); + mCallerOptions = options; + } + + /** + * Performs permission check and retrieves the options. + * + * @param r The record of the being started activity. + */ + ActivityOptions getOptions(ActivityRecord r) throws SecurityException { + return getOptions(r.intent, r.info, r.app, r.mStackSupervisor); + } + + /** + * Performs permission check and retrieves the options when options are not being used to launch + * a specific activity (i.e. a task is moved to front). + */ + ActivityOptions getOptions(ActivityStackSupervisor supervisor) throws SecurityException { + return getOptions(null, null, null, supervisor); + } + + /** + * Performs permission check and retrieves the options. + * + * @param intent The intent that is being launched. + * @param aInfo The info of the activity being launched. + * @param callerApp The record of the caller. + */ + ActivityOptions getOptions(@Nullable Intent intent, @Nullable ActivityInfo aInfo, + @Nullable ProcessRecord callerApp, + ActivityStackSupervisor supervisor) throws SecurityException { + if (mOriginalOptions != null) { + checkPermissions(intent, aInfo, callerApp, supervisor, mOriginalOptions, + mOriginalCallingPid, mOriginalCallingUid); + } + if (mCallerOptions != null) { + checkPermissions(intent, aInfo, callerApp, supervisor, mCallerOptions, + mRealCallingPid, mRealCallingUid); + } + return mergeActivityOptions(mOriginalOptions, mCallerOptions); + } + + /** + * @see ActivityOptions#popAppVerificationBundle + */ + Bundle popAppVerificationBundle() { + return mOriginalOptions != null ? mOriginalOptions.popAppVerificationBundle() : null; + } + + private void abort() { + if (mOriginalOptions != null) { + ActivityOptions.abort(mOriginalOptions); + } + if (mCallerOptions != null) { + ActivityOptions.abort(mCallerOptions); + } + } + + static void abort(@Nullable SafeActivityOptions options) { + if (options != null) { + options.abort(); + } + } + + /** + * Merges two activity options into one, with {@code options2} taking precedence in case of a + * conflict. + */ + @VisibleForTesting + @Nullable ActivityOptions mergeActivityOptions(@Nullable ActivityOptions options1, + @Nullable ActivityOptions options2) { + if (options1 == null) { + return options2; + } + if (options2 == null) { + return options1; + } + final Bundle b1 = options1.toBundle(); + final Bundle b2 = options2.toBundle(); + b1.putAll(b2); + return ActivityOptions.fromBundle(b1); + } + + private void checkPermissions(@Nullable Intent intent, @Nullable ActivityInfo aInfo, + @Nullable ProcessRecord callerApp, ActivityStackSupervisor supervisor, + ActivityOptions options, int callingPid, int callingUid) { + // If a launch task id is specified, then ensure that the caller is the recents + // component or has the START_TASKS_FROM_RECENTS permission + if (options.getLaunchTaskId() != INVALID_TASK_ID + && !supervisor.mRecentTasks.isCallerRecents(callingUid)) { + final int startInTaskPerm = supervisor.mService.checkPermission( + START_TASKS_FROM_RECENTS, callingPid, callingUid); + if (startInTaskPerm == PERMISSION_DENIED) { + final String msg = "Permission Denial: starting " + getIntentString(intent) + + " from " + callerApp + " (pid=" + callingPid + + ", uid=" + callingUid + ") with launchTaskId=" + + options.getLaunchTaskId(); + Slog.w(TAG, msg); + throw new SecurityException(msg); + } + } + // Check if someone tries to launch an activity on a private display with a different + // owner. + final int launchDisplayId = options.getLaunchDisplayId(); + if (aInfo != null && launchDisplayId != INVALID_DISPLAY + && !supervisor.isCallerAllowedToLaunchOnDisplay(callingPid, callingUid, + launchDisplayId, aInfo)) { + final String msg = "Permission Denial: starting " + getIntentString(intent) + + " from " + callerApp + " (pid=" + callingPid + + ", uid=" + callingUid + ") with launchDisplayId=" + + launchDisplayId; + Slog.w(TAG, msg); + throw new SecurityException(msg); + } + // Check if someone tries to launch an unwhitelisted activity into LockTask mode. + final boolean lockTaskMode = options.getLockTaskMode(); + if (aInfo != null && lockTaskMode + && !supervisor.mService.mLockTaskController.isPackageWhitelisted( + UserHandle.getUserId(callingUid), aInfo.packageName)) { + final String msg = "Permission Denial: starting " + getIntentString(intent) + + " from " + callerApp + " (pid=" + callingPid + + ", uid=" + callingUid + ") with lockTaskMode=true"; + Slog.w(TAG, msg); + throw new SecurityException(msg); + } + + // Check permission for remote animations + final RemoteAnimationAdapter adapter = options.getRemoteAnimationAdapter(); + if (adapter != null && supervisor.mService.checkPermission( + CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS, callingPid, callingUid) + != PERMISSION_GRANTED) { + final String msg = "Permission Denial: starting " + getIntentString(intent) + + " from " + callerApp + " (pid=" + callingPid + + ", uid=" + callingUid + ") with remoteAnimationAdapter"; + Slog.w(TAG, msg); + throw new SecurityException(msg); + } + } + + private String getIntentString(Intent intent) { + return intent != null ? intent.toString() : "(no intent)"; + } +} diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index a7147206bda2..f4c99f5e5491 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -63,6 +63,7 @@ import android.hardware.usb.UsbManager; import android.media.AudioAttributes; import android.media.AudioDevicePort; import android.media.AudioFocusInfo; +import android.media.AudioFocusRequest; import android.media.AudioSystem; import android.media.AudioFormat; import android.media.AudioManager; @@ -6003,6 +6004,44 @@ public class AudioService extends IAudioService.Stub //========================================================================================== // Audio Focus //========================================================================================== + /** + * Returns whether a focus request is eligible to force ducking. + * Will return true if: + * - the AudioAttributes have a usage of USAGE_ASSISTANCE_ACCESSIBILITY, + * - the focus request is AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, + * - the associated Bundle has KEY_ACCESSIBILITY_FORCE_FOCUS_DUCKING set to true, + * - the uid of the requester is a known accessibility service or root. + * @param aa AudioAttributes of the focus request + * @param uid uid of the focus requester + * @return true if ducking is to be forced + */ + private boolean forceFocusDuckingForAccessibility(@Nullable AudioAttributes aa, + int request, int uid) { + if (aa == null || aa.getUsage() != AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY + || request != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK) { + return false; + } + final Bundle extraInfo = aa.getBundle(); + if (extraInfo == null || + !extraInfo.getBoolean(AudioFocusRequest.KEY_ACCESSIBILITY_FORCE_FOCUS_DUCKING)) { + return false; + } + if (uid == 0) { + return true; + } + synchronized (mAccessibilityServiceUidsLock) { + if (mAccessibilityServiceUids != null) { + int callingUid = Binder.getCallingUid(); + for (int i = 0; i < mAccessibilityServiceUids.length; i++) { + if (mAccessibilityServiceUids[i] == callingUid) { + return true; + } + } + } + } + return false; + } + public int requestAudioFocus(AudioAttributes aa, int durationHint, IBinder cb, IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags, IAudioPolicyCallback pcb, int sdk) { @@ -6026,7 +6065,8 @@ public class AudioService extends IAudioService.Stub } return mMediaFocusControl.requestAudioFocus(aa, durationHint, cb, fd, - clientId, callingPackageName, flags, sdk); + clientId, callingPackageName, flags, sdk, + forceFocusDuckingForAccessibility(aa, durationHint, Binder.getCallingUid())); } public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, AudioAttributes aa, diff --git a/services/core/java/com/android/server/audio/FocusRequester.java b/services/core/java/com/android/server/audio/FocusRequester.java index 48f0d5a11e0a..f2ef02fb2579 100644 --- a/services/core/java/com/android/server/audio/FocusRequester.java +++ b/services/core/java/com/android/server/audio/FocusRequester.java @@ -307,9 +307,10 @@ public class FocusRequester { * @return true if the focus loss is definitive, false otherwise. */ @GuardedBy("MediaFocusControl.mAudioFocusLock") - boolean handleFocusLossFromGain(int focusGain, final FocusRequester frWinner) { + boolean handleFocusLossFromGain(int focusGain, final FocusRequester frWinner, boolean forceDuck) + { final int focusLoss = focusLossForGainRequest(focusGain); - handleFocusLoss(focusLoss, frWinner); + handleFocusLoss(focusLoss, frWinner, forceDuck); return (focusLoss == AudioManager.AUDIOFOCUS_LOSS); } @@ -343,7 +344,8 @@ public class FocusRequester { } @GuardedBy("MediaFocusControl.mAudioFocusLock") - void handleFocusLoss(int focusLoss, @Nullable final FocusRequester frWinner) { + void handleFocusLoss(int focusLoss, @Nullable final FocusRequester frWinner, boolean forceDuck) + { try { if (focusLoss != mFocusLossReceived) { mFocusLossReceived = focusLoss; @@ -374,19 +376,20 @@ public class FocusRequester { && frWinner != null) { // candidate for enforcement by the framework if (frWinner.mCallingUid != this.mCallingUid) { - if ((mGrantFlags - & AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS) != 0) { + if (!forceDuck && ((mGrantFlags + & AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS) != 0)) { // the focus loser declared it would pause instead of duck, let it // handle it (the framework doesn't pause for apps) handled = false; Log.v(TAG, "not ducking uid " + this.mCallingUid + " - flags"); - } else if (MediaFocusControl.ENFORCE_DUCKING_FOR_NEW && - this.getSdkTarget() <= MediaFocusControl.DUCKING_IN_APP_SDK_LEVEL) { + } else if (!forceDuck && (MediaFocusControl.ENFORCE_DUCKING_FOR_NEW && + this.getSdkTarget() <= MediaFocusControl.DUCKING_IN_APP_SDK_LEVEL)) + { // legacy behavior, apps used to be notified when they should be ducking handled = false; Log.v(TAG, "not ducking uid " + this.mCallingUid + " - old SDK"); } else { - handled = mFocusController.duckPlayers(frWinner, this); + handled = mFocusController.duckPlayers(frWinner, this, forceDuck); } } // else: the focus change is within the same app, so let the dispatching // happen as if the framework was not involved. diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java index de58b59a2423..9ddc52a1826e 100644 --- a/services/core/java/com/android/server/audio/MediaFocusControl.java +++ b/services/core/java/com/android/server/audio/MediaFocusControl.java @@ -101,8 +101,8 @@ public class MediaFocusControl implements PlayerFocusEnforcer { //================================================================= // PlayerFocusEnforcer implementation @Override - public boolean duckPlayers(FocusRequester winner, FocusRequester loser) { - return mFocusEnforcer.duckPlayers(winner, loser); + public boolean duckPlayers(FocusRequester winner, FocusRequester loser, boolean forceDuck) { + return mFocusEnforcer.duckPlayers(winner, loser, forceDuck); } @Override @@ -144,7 +144,8 @@ public class MediaFocusControl implements PlayerFocusEnforcer { if (!mFocusStack.empty()) { // notify the current focus owner it lost focus after removing it from stack final FocusRequester exFocusOwner = mFocusStack.pop(); - exFocusOwner.handleFocusLoss(AudioManager.AUDIOFOCUS_LOSS, null); + exFocusOwner.handleFocusLoss(AudioManager.AUDIOFOCUS_LOSS, null, + false /*forceDuck*/); exFocusOwner.release(); } } @@ -166,13 +167,14 @@ public class MediaFocusControl implements PlayerFocusEnforcer { * @param focusGain the new focus gain that will later be added at the top of the stack */ @GuardedBy("mAudioFocusLock") - private void propagateFocusLossFromGain_syncAf(int focusGain, final FocusRequester fr) { + private void propagateFocusLossFromGain_syncAf(int focusGain, final FocusRequester fr, + boolean forceDuck) { final List<String> clientsToRemove = new LinkedList<String>(); // going through the audio focus stack to signal new focus, traversing order doesn't // matter as all entries respond to the same external focus gain for (FocusRequester focusLoser : mFocusStack) { final boolean isDefinitiveLoss = - focusLoser.handleFocusLossFromGain(focusGain, fr); + focusLoser.handleFocusLossFromGain(focusGain, fr, forceDuck); if (isDefinitiveLoss) { clientsToRemove.add(focusLoser.getClientId()); } @@ -347,7 +349,7 @@ public class MediaFocusControl implements PlayerFocusEnforcer { Log.e(TAG, "No exclusive focus owner found in propagateFocusLossFromGain_syncAf()", new Exception()); // no exclusive owner, push at top of stack, focus is granted, propagate change - propagateFocusLossFromGain_syncAf(nfr.getGainRequest(), nfr); + propagateFocusLossFromGain_syncAf(nfr.getGainRequest(), nfr, false /*forceDuck*/); mFocusStack.push(nfr); return AudioManager.AUDIOFOCUS_REQUEST_GRANTED; } else { @@ -664,7 +666,7 @@ public class MediaFocusControl implements PlayerFocusEnforcer { /** @see AudioManager#requestAudioFocus(AudioManager.OnAudioFocusChangeListener, int, int, int) */ protected int requestAudioFocus(AudioAttributes aa, int focusChangeHint, IBinder cb, IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags, - int sdk) { + int sdk, boolean forceDuck) { mEventLogger.log((new AudioEventLogger.StringEvent( "requestAudioFocus() from uid/pid " + Binder.getCallingUid() + "/" + Binder.getCallingPid() @@ -777,7 +779,7 @@ public class MediaFocusControl implements PlayerFocusEnforcer { } else { // propagate the focus change through the stack if (!mFocusStack.empty()) { - propagateFocusLossFromGain_syncAf(focusChangeHint, nfr); + propagateFocusLossFromGain_syncAf(focusChangeHint, nfr, forceDuck); } // push focus requester at the top of the audio focus stack diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java index 494317334f43..ff864536e9af 100644 --- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java +++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java @@ -421,7 +421,7 @@ public final class PlaybackActivityMonitor private final DuckingManager mDuckingManager = new DuckingManager(); @Override - public boolean duckPlayers(FocusRequester winner, FocusRequester loser) { + public boolean duckPlayers(FocusRequester winner, FocusRequester loser, boolean forceDuck) { if (DEBUG) { Log.v(TAG, String.format("duckPlayers: uids winner=%d loser=%d", winner.getClientUid(), loser.getClientUid())); @@ -441,8 +441,8 @@ public final class PlaybackActivityMonitor && loser.hasSameUid(apc.getClientUid()) && apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED) { - if (apc.getAudioAttributes().getContentType() == - AudioAttributes.CONTENT_TYPE_SPEECH) { + if (!forceDuck && (apc.getAudioAttributes().getContentType() == + AudioAttributes.CONTENT_TYPE_SPEECH)) { // the player is speaking, ducking will make the speech unintelligible // so let the app handle it instead Log.v(TAG, "not ducking player " + apc.getPlayerInterfaceId() diff --git a/services/core/java/com/android/server/audio/PlayerFocusEnforcer.java b/services/core/java/com/android/server/audio/PlayerFocusEnforcer.java index 0733eca97d4e..3c834daf3c8a 100644 --- a/services/core/java/com/android/server/audio/PlayerFocusEnforcer.java +++ b/services/core/java/com/android/server/audio/PlayerFocusEnforcer.java @@ -25,7 +25,7 @@ public interface PlayerFocusEnforcer { * @param loser * @return */ - public boolean duckPlayers(FocusRequester winner, FocusRequester loser); + public boolean duckPlayers(FocusRequester winner, FocusRequester loser, boolean forceDuck); public void unduckPlayers(FocusRequester winner); diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index b97de6511aed..c77ec20afa3b 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -1849,7 +1849,6 @@ public final class DisplayManagerService extends SystemService { if (packageName != null && !validatePackageName(getCallingUid(), packageName)) { packageName = null; } - Preconditions.checkNotNull(c); final long token = Binder.clearCallingIdentity(); try { setBrightnessConfigurationForUserInternal(c, userId, packageName); diff --git a/services/core/java/com/android/server/display/PersistentDataStore.java b/services/core/java/com/android/server/display/PersistentDataStore.java index f1ce5c5f0007..cbf46f832186 100644 --- a/services/core/java/com/android/server/display/PersistentDataStore.java +++ b/services/core/java/com/android/server/display/PersistentDataStore.java @@ -598,14 +598,20 @@ final class PersistentDataStore { private boolean setBrightnessConfigurationForUser(BrightnessConfiguration c, int userSerial, String packageName) { BrightnessConfiguration currentConfig = mConfigurations.get(userSerial); - if (currentConfig == null || !currentConfig.equals(c)) { - if (packageName == null) { - mPackageNames.remove(userSerial); + if (currentConfig != c && (currentConfig == null || !currentConfig.equals(c))) { + if (c != null) { + if (packageName == null) { + mPackageNames.remove(userSerial); + } else { + mPackageNames.put(userSerial, packageName); + } + mTimeStamps.put(userSerial, System.currentTimeMillis()); + mConfigurations.put(userSerial, c); } else { - mPackageNames.put(userSerial, packageName); + mPackageNames.remove(userSerial); + mTimeStamps.delete(userSerial); + mConfigurations.remove(userSerial); } - mTimeStamps.put(userSerial, System.currentTimeMillis()); - mConfigurations.put(userSerial, c); return true; } return false; diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 07ea51be4ba0..a6753ab09103 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -53,6 +53,7 @@ import android.content.pm.UserInfo; import android.content.res.Resources; import android.database.ContentObserver; import android.database.sqlite.SQLiteDatabase; +import android.hardware.authsecret.V1_0.IAuthSecret; import android.net.Uri; import android.os.Binder; import android.os.Bundle; @@ -77,10 +78,10 @@ import android.security.KeyStore; import android.security.keystore.AndroidKeyStoreProvider; import android.security.keystore.KeyProperties; import android.security.keystore.KeyProtection; -import android.security.keystore.KeychainProtectionParams; import android.security.keystore.UserNotAuthenticatedException; -import android.security.keystore.WrappedApplicationKey; -import android.security.keystore.KeychainSnapshot; +import android.security.keystore.recovery.KeychainProtectionParams; +import android.security.keystore.recovery.WrappedApplicationKey; +import android.security.keystore.recovery.KeychainSnapshot; import android.service.gatekeeper.GateKeeperResponse; import android.service.gatekeeper.IGateKeeperService; import android.text.TextUtils; @@ -126,8 +127,10 @@ import java.security.SecureRandom; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.util.Arrays; +import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -183,6 +186,7 @@ public class LockSettingsService extends ILockSettings.Stub { private boolean mFirstCallToVold; protected IGateKeeperService mGateKeeperService; + protected IAuthSecret mAuthSecretService; /** * The UIDs that are used for system credential storage in keystore. @@ -613,6 +617,14 @@ public class LockSettingsService extends ILockSettings.Stub { } catch (RemoteException e) { Slog.e(TAG, "Failure retrieving IGateKeeperService", e); } + // Find the AuthSecret HAL + try { + mAuthSecretService = IAuthSecret.getService(); + } catch (NoSuchElementException e) { + Slog.i(TAG, "Device doesn't implement AuthSecret HAL"); + } catch (RemoteException e) { + Slog.w(TAG, "Failed to get AuthSecret HAL", e); + } mDeviceProvisionedObserver.onSystemReady(); // TODO: maybe skip this for split system user mode. mStorage.prefetchUser(UserHandle.USER_SYSTEM); @@ -2127,6 +2139,20 @@ public class LockSettingsService extends ILockSettings.Stub { private SparseArray<AuthenticationToken> mSpCache = new SparseArray(); private void onAuthTokenKnownForUser(@UserIdInt int userId, AuthenticationToken auth) { + // Pass the primary user's auth secret to the HAL + if (mAuthSecretService != null && mUserManager.getUserInfo(userId).isPrimary()) { + try { + final byte[] rawSecret = auth.deriveVendorAuthSecret(); + final ArrayList<Byte> secret = new ArrayList<>(rawSecret.length); + for (int i = 0; i < rawSecret.length; ++i) { + secret.add(rawSecret[i]); + } + mAuthSecretService.primaryUserCredential(secret); + } catch (RemoteException e) { + Slog.w(TAG, "Failed to pass primary user secret to AuthSecret HAL", e); + } + } + // Update the SP cache, removing the entry when allowed synchronized (mSpManager) { if (shouldCacheSpForUser(userId)) { diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java index 7a3a746e1868..88b2a3685088 100644 --- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java +++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java @@ -121,6 +121,7 @@ public class SyntheticPasswordManager { private static final byte[] PERSONALIZATION_USER_GK_AUTH = "user-gk-authentication".getBytes(); private static final byte[] PERSONALIZATION_SP_GK_AUTH = "sp-gk-authentication".getBytes(); private static final byte[] PERSONALIZATION_FBE_KEY = "fbe-key".getBytes(); + private static final byte[] PERSONALIZATION_AUTHSECRET_KEY = "authsecret-hal".getBytes(); private static final byte[] PERSONALIZATION_SP_SPLIT = "sp-split".getBytes(); private static final byte[] PERSONALIZATION_E0 = "e0-encryption".getBytes(); private static final byte[] PERSONALISATION_WEAVER_PASSWORD = "weaver-pwd".getBytes(); @@ -159,6 +160,11 @@ public class SyntheticPasswordManager { syntheticPassword.getBytes()); } + public byte[] deriveVendorAuthSecret() { + return SyntheticPasswordCrypto.personalisedHash(PERSONALIZATION_AUTHSECRET_KEY, + syntheticPassword.getBytes()); + } + private void initialize(byte[] P0, byte[] P1) { this.P1 = P1; this.syntheticPassword = String.valueOf(HexEncoding.encode( diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java index 452c9eea79e8..6fcbcbcbfad9 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java @@ -16,14 +16,14 @@ package com.android.server.locksettings.recoverablekeystore; -import static android.security.keystore.KeychainProtectionParams.TYPE_LOCKSCREEN; +import static android.security.keystore.recovery.KeychainProtectionParams.TYPE_LOCKSCREEN; import android.annotation.Nullable; import android.content.Context; -import android.security.keystore.KeyDerivationParams; -import android.security.keystore.KeychainProtectionParams; -import android.security.keystore.KeychainSnapshot; -import android.security.keystore.WrappedApplicationKey; +import android.security.keystore.recovery.KeyDerivationParams; +import android.security.keystore.recovery.KeychainProtectionParams; +import android.security.keystore.recovery.KeychainSnapshot; +import android.security.keystore.recovery.WrappedApplicationKey; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java index 76508d5817e2..ac3cef2fa7ef 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java @@ -33,10 +33,10 @@ import android.os.RemoteException; import android.os.ServiceSpecificException; import android.os.UserHandle; -import android.security.keystore.KeychainProtectionParams; -import android.security.keystore.KeychainSnapshot; -import android.security.keystore.RecoveryController; -import android.security.keystore.WrappedApplicationKey; +import android.security.keystore.recovery.KeychainProtectionParams; +import android.security.keystore.recovery.KeychainSnapshot; +import android.security.keystore.recovery.RecoveryController; +import android.security.keystore.recovery.WrappedApplicationKey; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorage.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorage.java index 62bb41ec48aa..7cde7ab0589c 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorage.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorage.java @@ -17,7 +17,7 @@ package com.android.server.locksettings.recoverablekeystore.storage; import android.annotation.Nullable; -import android.security.keystore.KeychainSnapshot; +import android.security.keystore.recovery.KeychainSnapshot; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; diff --git a/services/core/java/com/android/server/net/watchlist/NetworkWatchlistService.java b/services/core/java/com/android/server/net/watchlist/NetworkWatchlistService.java index 239ddbeb5f86..7165e600ca2f 100644 --- a/services/core/java/com/android/server/net/watchlist/NetworkWatchlistService.java +++ b/services/core/java/com/android/server/net/watchlist/NetworkWatchlistService.java @@ -16,6 +16,7 @@ package com.android.server.net.watchlist; +import android.annotation.Nullable; import android.content.Context; import android.net.IIpConnectivityMetrics; import android.net.INetdEventCallback; @@ -210,6 +211,12 @@ public class NetworkWatchlistService extends INetworkWatchlistManager.Stub { return stopWatchlistLoggingImpl(); } + @Nullable + @Override + public byte[] getWatchlistConfigHash() { + return mConfig.getWatchlistConfigHash(); + } + private void enforceWatchlistLoggingPermission() { final int uid = Binder.getCallingUid(); if (uid != Process.SYSTEM_UID) { diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java index 1717b3d1a5f7..14995b3827e1 100644 --- a/services/core/java/com/android/server/pm/LauncherAppsService.java +++ b/services/core/java/com/android/server/pm/LauncherAppsService.java @@ -560,7 +560,6 @@ public class LauncherAppsService extends SystemService { private boolean startShortcutIntentsAsPublisher(@NonNull Intent[] intents, @NonNull String publisherPackage, Bundle startActivityOptions, int userId) { final int code; - final long ident = injectClearCallingIdentity(); try { code = mActivityManagerInternal.startActivitiesAsPackage(publisherPackage, userId, intents, startActivityOptions); @@ -575,8 +574,6 @@ public class LauncherAppsService extends SystemService { Slog.d(TAG, "SecurityException while launching intent", e); } return false; - } finally { - injectRestoreCallingIdentity(ident); } } diff --git a/services/core/java/com/android/server/timezone/RulesManagerService.java b/services/core/java/com/android/server/timezone/RulesManagerService.java index 30fc63c2a1b0..be9b204721db 100644 --- a/services/core/java/com/android/server/timezone/RulesManagerService.java +++ b/services/core/java/com/android/server/timezone/RulesManagerService.java @@ -143,6 +143,26 @@ public final class RulesManagerService extends IRulesManager.Stub { return null; } + // Determine the installed distro state. This should be possible regardless of whether + // there's an operation in progress. + DistroVersion installedDistroVersion; + int distroStatus = DISTRO_STATUS_UNKNOWN; + DistroRulesVersion installedDistroRulesVersion = null; + try { + installedDistroVersion = mInstaller.getInstalledDistroVersion(); + if (installedDistroVersion == null) { + distroStatus = DISTRO_STATUS_NONE; + installedDistroRulesVersion = null; + } else { + distroStatus = DISTRO_STATUS_INSTALLED; + installedDistroRulesVersion = new DistroRulesVersion( + installedDistroVersion.rulesVersion, + installedDistroVersion.revision); + } + } catch (DistroException | IOException e) { + Slog.w(TAG, "Failed to read installed distro.", e); + } + boolean operationInProgress = this.mOperationInProgress.get(); // Determine the staged operation status, if possible. @@ -168,27 +188,6 @@ public final class RulesManagerService extends IRulesManager.Stub { Slog.w(TAG, "Failed to read staged distro.", e); } } - - // Determine the installed distro state, if possible. - DistroVersion installedDistroVersion; - int distroStatus = DISTRO_STATUS_UNKNOWN; - DistroRulesVersion installedDistroRulesVersion = null; - if (!operationInProgress) { - try { - installedDistroVersion = mInstaller.getInstalledDistroVersion(); - if (installedDistroVersion == null) { - distroStatus = DISTRO_STATUS_NONE; - installedDistroRulesVersion = null; - } else { - distroStatus = DISTRO_STATUS_INSTALLED; - installedDistroRulesVersion = new DistroRulesVersion( - installedDistroVersion.rulesVersion, - installedDistroVersion.revision); - } - } catch (DistroException | IOException e) { - Slog.w(TAG, "Failed to read installed distro.", e); - } - } return new RulesState(systemRulesVersion, DISTRO_FORMAT_VERSION_SUPPORTED, operationInProgress, stagedOperationStatus, stagedDistroRulesVersion, distroStatus, installedDistroRulesVersion); diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java index 589a89bcbddf..b58c7003f39e 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java @@ -228,8 +228,8 @@ public class ActivityStarterTests extends ActivityTestsBase { if (containsConditions(preconditions,PRECONDITION_CANNOT_START_ANY_ACTIVITY)) { doReturn(false).when(service.mStackSupervisor).checkStartAnyActivityPermission( - any(), any(), any(), anyInt(), anyInt(), anyInt(), any(), anyBoolean(), - any(), any(), any(), any()); + any(), any(), any(), anyInt(), anyInt(), anyInt(), any(), + anyBoolean(), any(), any(), any()); } try { @@ -278,7 +278,7 @@ public class ActivityStarterTests extends ActivityTestsBase { .setResultTo(resultTo) .setRequestCode(requestCode) .setReason("testLaunchActivityPermissionDenied") - .setActivityOptions(options) + .setActivityOptions(new SafeActivityOptions(options)) .execute(); verify(options, times(1)).abort(); } diff --git a/services/tests/servicestests/src/com/android/server/am/SafeActivityOptionsTest.java b/services/tests/servicestests/src/com/android/server/am/SafeActivityOptionsTest.java new file mode 100644 index 000000000000..168bc1782d56 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/am/SafeActivityOptionsTest.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.server.am; + +import static org.junit.Assert.assertEquals; + +import android.app.ActivityOptions; +import android.platform.test.annotations.Presubmit; +import android.support.test.filters.FlakyTest; +import android.support.test.filters.MediumTest; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@MediumTest +@Presubmit +@FlakyTest +@RunWith(AndroidJUnit4.class) +public class SafeActivityOptionsTest { + + @Test + public void testMerge() { + final ActivityOptions opts1 = ActivityOptions.makeBasic(); + opts1.setLaunchDisplayId(5); + final ActivityOptions opts2 = ActivityOptions.makeBasic(); + opts2.setLaunchDisplayId(6); + final SafeActivityOptions options = new SafeActivityOptions(opts1); + final ActivityOptions result = options.mergeActivityOptions(opts1, opts2); + assertEquals(6, result.getLaunchDisplayId()); + } +} diff --git a/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java b/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java index 9cac536bead6..613d0afea183 100644 --- a/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java +++ b/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java @@ -87,6 +87,11 @@ public class PackageManagerStub extends PackageManager { } @Override + public Intent getCarLaunchIntentForPackage(String packageName) { + return null; + } + + @Override public int[] getPackageGids(String packageName) throws NameNotFoundException { return new int[0]; } diff --git a/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java b/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java index c5f8c90dd6c6..675000e91a1c 100644 --- a/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java +++ b/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java @@ -171,6 +171,23 @@ public class PersistentDataStoreTest { newDataStore.getBrightnessConfiguration(0 /*userSerial*/)); } + @Test + public void testNullBrightnessConfiguration() { + final float[] lux = { 0f, 10f }; + final float[] nits = {1f, 100f }; + final BrightnessConfiguration config = new BrightnessConfiguration.Builder(lux, nits) + .setDescription("a description") + .build(); + mDataStore.loadIfNeeded(); + assertNull(mDataStore.getBrightnessConfiguration(0 /*userSerial*/)); + + mDataStore.setBrightnessConfigurationForUser(config, 0, "packagename"); + assertNotNull(mDataStore.getBrightnessConfiguration(0 /*userSerial*/)); + + mDataStore.setBrightnessConfigurationForUser(null, 0, "packagename"); + assertNull(mDataStore.getBrightnessConfiguration(0 /*userSerial*/)); + } + public class TestInjector extends PersistentDataStore.Injector { private InputStream mReadStream; private OutputStream mWriteStream; diff --git a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java index 272b5d899d4b..e8648701bd0d 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java @@ -31,6 +31,7 @@ import android.app.admin.DevicePolicyManagerInternal; import android.app.trust.TrustManager; import android.content.ComponentName; import android.content.pm.UserInfo; +import android.hardware.authsecret.V1_0.IAuthSecret; import android.os.FileUtils; import android.os.IProgressListener; import android.os.RemoteException; @@ -80,6 +81,7 @@ public class BaseLockSettingsServiceTests extends AndroidTestCase { DevicePolicyManagerInternal mDevicePolicyManagerInternal; KeyStore mKeyStore; MockSyntheticPasswordManager mSpManager; + IAuthSecret mAuthSecretService; @Override protected void setUp() throws Exception { @@ -115,17 +117,21 @@ public class BaseLockSettingsServiceTests extends AndroidTestCase { }; mSpManager = new MockSyntheticPasswordManager(mContext, mStorage, mGateKeeperService, mUserManager); + mAuthSecretService = mock(IAuthSecret.class); mService = new LockSettingsServiceTestable(mContext, mLockPatternUtils, mStorage, mGateKeeperService, mKeyStore, setUpStorageManagerMock(), mActivityManager, - mSpManager); + mSpManager, mAuthSecretService); when(mUserManager.getUserInfo(eq(PRIMARY_USER_ID))).thenReturn(PRIMARY_USER_INFO); mPrimaryUserProfiles.add(PRIMARY_USER_INFO); installChildProfile(MANAGED_PROFILE_USER_ID); installAndTurnOffChildProfile(TURNED_OFF_PROFILE_USER_ID); - when(mUserManager.getUsers(anyBoolean())).thenReturn(mPrimaryUserProfiles); when(mUserManager.getProfiles(eq(PRIMARY_USER_ID))).thenReturn(mPrimaryUserProfiles); when(mUserManager.getUserInfo(eq(SECONDARY_USER_ID))).thenReturn(SECONDARY_USER_INFO); + final ArrayList<UserInfo> allUsers = new ArrayList<>(mPrimaryUserProfiles); + allUsers.add(SECONDARY_USER_INFO); + when(mUserManager.getUsers(anyBoolean())).thenReturn(allUsers); + when(mActivityManager.unlockUser(anyInt(), any(), any(), any())).thenAnswer( new Answer<Boolean>() { @Override diff --git a/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java index 4ad9f19735c4..d2caa0af0ba2 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java @@ -22,6 +22,7 @@ import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSW import static com.android.server.testutils.TestUtils.assertExpectException; import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.when; import static org.mockito.Mockito.verify; @@ -31,6 +32,10 @@ import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.VerifyCredentialResponse; import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationResult; +import java.util.ArrayList; + +import org.mockito.ArgumentCaptor; + /** * Run the synthetic password tests with caching enabled. * @@ -88,6 +93,26 @@ public class CachedSyntheticPasswordTests extends SyntheticPasswordTests { .getResponseCode()); } + public void testUntrustedCredentialChangeMaintainsAuthSecret() throws RemoteException { + final String PASSWORD = "testUntrustedCredentialChangeMaintainsAuthSecret-password"; + final String NEWPASSWORD = "testUntrustedCredentialChangeMaintainsAuthSecret-newpassword"; + + initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID); + // Untrusted change password + mService.setLockCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + + // Verify the password + assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( + NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID) + .getResponseCode()); + + // Ensure the same secret was passed each time + ArgumentCaptor<ArrayList<Byte>> secret = ArgumentCaptor.forClass(ArrayList.class); + verify(mAuthSecretService, atLeastOnce()).primaryUserCredential(secret.capture()); + assertEquals(1, secret.getAllValues().stream().distinct().count()); + } + public void testUntrustedCredentialChangeBlockedIfSpNotCached() throws RemoteException { final String PASSWORD = "testUntrustedCredentialChangeBlockedIfSpNotCached-password"; final String NEWPASSWORD = "testUntrustedCredentialChangeBlockedIfSpNotCached-newpassword"; diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java index 0916a335b51e..fe683abe7e1b 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java @@ -20,6 +20,7 @@ import static org.mockito.Mockito.mock; import android.app.IActivityManager; import android.content.Context; +import android.hardware.authsecret.V1_0.IAuthSecret; import android.os.Handler; import android.os.Looper; import android.os.Process; @@ -42,10 +43,12 @@ public class LockSettingsServiceTestable extends LockSettingsService { private LockPatternUtils mLockPatternUtils; private IStorageManager mStorageManager; private SyntheticPasswordManager mSpManager; + private IAuthSecret mAuthSecretService; public MockInjector(Context context, LockSettingsStorage storage, KeyStore keyStore, IActivityManager activityManager, LockPatternUtils lockPatternUtils, - IStorageManager storageManager, SyntheticPasswordManager spManager) { + IStorageManager storageManager, SyntheticPasswordManager spManager, + IAuthSecret authSecretService) { super(context); mLockSettingsStorage = storage; mKeyStore = keyStore; @@ -109,10 +112,11 @@ public class LockSettingsServiceTestable extends LockSettingsService { protected LockSettingsServiceTestable(Context context, LockPatternUtils lockPatternUtils, LockSettingsStorage storage, FakeGateKeeperService gatekeeper, KeyStore keystore, IStorageManager storageManager, IActivityManager mActivityManager, - SyntheticPasswordManager spManager) { + SyntheticPasswordManager spManager, IAuthSecret authSecretService) { super(new MockInjector(context, storage, keystore, mActivityManager, lockPatternUtils, - storageManager, spManager)); + storageManager, spManager, authSecretService)); mGateKeeperService = gatekeeper; + mAuthSecretService = authSecretService; } @Override diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java index b07d6ac5dc04..294c3e99ad7e 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java @@ -24,6 +24,10 @@ import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSW import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_ENABLED_KEY; import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_HANDLE_KEY; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import android.app.admin.PasswordMetrics; @@ -36,6 +40,10 @@ import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationRe import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationToken; import com.android.server.locksettings.SyntheticPasswordManager.PasswordData; +import java.util.ArrayList; + +import org.mockito.ArgumentCaptor; + /** * runtest frameworks-services -c com.android.server.locksettings.SyntheticPasswordTests @@ -169,6 +177,46 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { assertNotEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); } + public void testSyntheticPasswordChangeCredentialKeepsAuthSecret() throws RemoteException { + final String PASSWORD = "testSyntheticPasswordChangeCredentialKeepsAuthSecret-password"; + final String NEWPASSWORD = "testSyntheticPasswordChangeCredentialKeepsAuthSecret-new"; + + initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID); + mService.setLockCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, PASSWORD, + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( + NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID) + .getResponseCode()); + + // Check the same secret was passed each time + ArgumentCaptor<ArrayList<Byte>> secret = ArgumentCaptor.forClass(ArrayList.class); + verify(mAuthSecretService, atLeastOnce()).primaryUserCredential(secret.capture()); + assertEquals(1, secret.getAllValues().stream().distinct().count()); + } + + public void testSyntheticPasswordVerifyPassesPrimaryUserAuthSecret() throws RemoteException { + final String PASSWORD = "testSyntheticPasswordVerifyPassesPrimaryUserAuthSecret-password"; + final String NEWPASSWORD = "testSyntheticPasswordVerifyPassesPrimaryUserAuthSecret-new"; + + initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID); + reset(mAuthSecretService); + assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( + PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID) + .getResponseCode()); + verify(mAuthSecretService).primaryUserCredential(any(ArrayList.class)); + } + + public void testSecondaryUserDoesNotPassAuthSecret() throws RemoteException { + final String PASSWORD = "testSecondaryUserDoesNotPassAuthSecret-password"; + final String NEWPASSWORD = "testSecondaryUserDoesNotPassAuthSecret-new"; + + initializeCredentialUnderSP(PASSWORD, SECONDARY_USER_ID); + assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( + PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, SECONDARY_USER_ID) + .getResponseCode()); + verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class)); + } + public void testManagedProfileUnifiedChallengeMigration() throws RemoteException { final String UnifiedPassword = "testManagedProfileUnifiedChallengeMigration-pwd"; disableSyntheticPassword(); diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java index 7eec4fea64dc..6edaf87e135f 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java @@ -16,11 +16,11 @@ package com.android.server.locksettings.recoverablekeystore; -import static android.security.keystore.KeychainProtectionParams.TYPE_LOCKSCREEN; +import static android.security.keystore.recovery.KeychainProtectionParams.TYPE_LOCKSCREEN; -import static android.security.keystore.KeychainProtectionParams.TYPE_PASSWORD; -import static android.security.keystore.KeychainProtectionParams.TYPE_PATTERN; -import static android.security.keystore.KeychainProtectionParams.TYPE_PIN; +import static android.security.keystore.recovery.KeychainProtectionParams.TYPE_PASSWORD; +import static android.security.keystore.recovery.KeychainProtectionParams.TYPE_PATTERN; +import static android.security.keystore.recovery.KeychainProtectionParams.TYPE_PIN; import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD; import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN; @@ -40,9 +40,9 @@ import android.content.Context; import android.security.keystore.AndroidKeyStoreSecretKey; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; -import android.security.keystore.KeyDerivationParams; -import android.security.keystore.KeychainSnapshot; -import android.security.keystore.WrappedApplicationKey; +import android.security.keystore.recovery.KeyDerivationParams; +import android.security.keystore.recovery.KeychainSnapshot; +import android.security.keystore.recovery.WrappedApplicationKey; import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java index 970bc33337da..a3a2e4764edc 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java @@ -16,8 +16,8 @@ package com.android.server.locksettings.recoverablekeystore; -import static android.security.keystore.KeychainProtectionParams.TYPE_LOCKSCREEN; -import static android.security.keystore.KeychainProtectionParams.TYPE_PASSWORD; +import static android.security.keystore.recovery.KeychainProtectionParams.TYPE_LOCKSCREEN; +import static android.security.keystore.recovery.KeychainProtectionParams.TYPE_PASSWORD; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertArrayEquals; @@ -42,9 +42,9 @@ import android.os.UserHandle; import android.security.keystore.AndroidKeyStoreSecretKey; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; -import android.security.keystore.KeyDerivationParams; -import android.security.keystore.KeychainProtectionParams; -import android.security.keystore.WrappedApplicationKey; +import android.security.keystore.recovery.KeyDerivationParams; +import android.security.keystore.recovery.KeychainProtectionParams; +import android.security.keystore.recovery.WrappedApplicationKey; import android.support.test.filters.SmallTest; import android.support.test.InstrumentationRegistry; import android.support.test.runner.AndroidJUnit4; diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorageTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorageTest.java index 56b44e2fa17c..89c5c6c8a072 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorageTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorageTest.java @@ -3,7 +3,7 @@ package com.android.server.locksettings.recoverablekeystore.storage; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; -import android.security.keystore.KeychainSnapshot; +import android.security.keystore.recovery.KeychainSnapshot; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; diff --git a/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java index d09d0c8d9e5c..1cfae1ef1a6d 100644 --- a/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java @@ -289,11 +289,13 @@ public class RulesManagerServiceTest { // Request the rules state while the async operation is "happening". RulesState actualRulesState = mRulesManagerService.getRulesState(); + DistroRulesVersion expectedInstalledDistroRulesVersion = + new DistroRulesVersion(installedRulesVersion, revision); RulesState expectedRuleState = new RulesState( systemRulesVersion, RulesManagerService.DISTRO_FORMAT_VERSION_SUPPORTED, true /* operationInProgress */, RulesState.STAGED_OPERATION_UNKNOWN, null /* stagedDistroRulesVersion */, - RulesState.DISTRO_STATUS_UNKNOWN, null /* installedDistroRulesVersion */); + RulesState.DISTRO_STATUS_INSTALLED, expectedInstalledDistroRulesVersion); assertEquals(expectedRuleState, actualRulesState); } diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java b/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java index f8db4faaa81f..794d0336904a 100644 --- a/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java +++ b/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java @@ -54,7 +54,7 @@ public class WindowAnimationSpecTest { @Test public void testApply_clipNone() { Rect windowCrop = new Rect(0, 0, 20, 20); - Animation a = new ClipRectAnimation(windowCrop, windowCrop); + Animation a = createClipRectAnimation(windowCrop, windowCrop); WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null, mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_NONE); windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0); @@ -99,7 +99,8 @@ public class WindowAnimationSpecTest { public void testApply_clipBeforeNoStackBounds() { // Stack bounds is (0, 0, 0, 0) animation clip is (0, 0, 20, 20) Rect windowCrop = new Rect(0, 0, 20, 20); - Animation a = new ClipRectAnimation(windowCrop, windowCrop); + Animation a = createClipRectAnimation(windowCrop, windowCrop); + a.initialize(0, 0, 0, 0); WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null, null, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM); windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0); @@ -110,7 +111,7 @@ public class WindowAnimationSpecTest { public void testApply_clipBeforeSmallerAnimationClip() { // Stack bounds is (0, 0, 10, 10) animation clip is (0, 0, 5, 5) Rect windowCrop = new Rect(0, 0, 5, 5); - Animation a = new ClipRectAnimation(windowCrop, windowCrop); + Animation a = createClipRectAnimation(windowCrop, windowCrop); WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null, mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM); windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0); @@ -122,11 +123,17 @@ public class WindowAnimationSpecTest { public void testApply_clipBeforeSmallerStackClip() { // Stack bounds is (0, 0, 10, 10) animation clip is (0, 0, 20, 20) Rect windowCrop = new Rect(0, 0, 20, 20); - Animation a = new ClipRectAnimation(windowCrop, windowCrop); + Animation a = createClipRectAnimation(windowCrop, windowCrop); WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null, mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM); windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0); verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(rect -> rect.equals(mStackBounds))); } + + private Animation createClipRectAnimation(Rect fromClip, Rect toClip) { + Animation a = new ClipRectAnimation(fromClip, toClip); + a.initialize(0, 0, 0, 0); + return a; + } } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 17f809d3863a..e33b25ea8286 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -2136,8 +2136,8 @@ public class TelephonyManager { public static final int SIM_STATE_PRESENT = 11; /** - * Extra included in {@link Intent.ACTION_SIM_CARD_STATE_CHANGED} and - * {@link Intent.ACTION_SIM_APPLICATION_STATE_CHANGED} to indicate the card/application state. + * Extra included in {@link #ACTION_SIM_CARD_STATE_CHANGED} and + * {@link #ACTION_SIM_APPLICATION_STATE_CHANGED} to indicate the card/application state. * * @hide */ @@ -2145,6 +2145,89 @@ public class TelephonyManager { public static final String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE"; /** + * Broadcast Action: The sim card state has changed. + * The intent will have the following extra values:</p> + * <dl> + * <dt>{@link #EXTRA_SIM_STATE}</dt> + * <dd>The sim card state. One of: + * <dl> + * <dt>{@link #SIM_STATE_ABSENT}</dt> + * <dd>SIM card not found</dd> + * <dt>{@link #SIM_STATE_CARD_IO_ERROR}</dt> + * <dd>SIM card IO error</dd> + * <dt>{@link #SIM_STATE_CARD_RESTRICTED}</dt> + * <dd>SIM card is restricted</dd> + * <dt>{@link #SIM_STATE_PRESENT}</dt> + * <dd>SIM card is present</dd> + * </dl> + * </dd> + * </dl> + * + * <p class="note">Requires the READ_PRIVILEGED_PHONE_STATE permission. + * + * <p class="note">The current state can also be queried using {@link #getSimCardState()}. + * + * <p class="note">This is a protected intent that can only be sent by the system. + * @hide + */ + @SystemApi + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_SIM_CARD_STATE_CHANGED = + "android.telephony.action.SIM_CARD_STATE_CHANGED"; + + /** + * Broadcast Action: The sim application state has changed. + * The intent will have the following extra values:</p> + * <dl> + * <dt>{@link #EXTRA_SIM_STATE}</dt> + * <dd>The sim application state. One of: + * <dl> + * <dt>{@link #SIM_STATE_NOT_READY}</dt> + * <dd>SIM card applications not ready</dd> + * <dt>{@link #SIM_STATE_PIN_REQUIRED}</dt> + * <dd>SIM card PIN locked</dd> + * <dt>{@link #SIM_STATE_PUK_REQUIRED}</dt> + * <dd>SIM card PUK locked</dd> + * <dt>{@link #SIM_STATE_NETWORK_LOCKED}</dt> + * <dd>SIM card network locked</dd> + * <dt>{@link #SIM_STATE_PERM_DISABLED}</dt> + * <dd>SIM card permanently disabled due to PUK failures</dd> + * <dt>{@link #SIM_STATE_LOADED}</dt> + * <dd>SIM card data loaded</dd> + * </dl> + * </dd> + * </dl> + * + * <p class="note">Requires the READ_PRIVILEGED_PHONE_STATE permission. + * + * <p class="note">The current state can also be queried using + * {@link #getSimApplicationState()}. + * + * <p class="note">This is a protected intent that can only be sent by the system. + * @hide + */ + @SystemApi + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = + "android.telephony.action.SIM_APPLICATION_STATE_CHANGED"; + + /** + * Broadcast Action: Status of the SIM slots on the device has changed. + * + * <p class="note">Requires the READ_PRIVILEGED_PHONE_STATE permission. + * + * <p class="note">The status can be queried using + * {@link #getUiccSlotsInfo()} + * + * <p class="note">This is a protected intent that can only be sent by the system. + * @hide + */ + @SystemApi + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_SIM_SLOT_STATUS_CHANGED = + "android.telephony.action.SIM_SLOT_STATUS_CHANGED"; + + /** * @return true if a ICC card is present */ public boolean hasIccCard() { diff --git a/test-mock/src/android/test/mock/MockPackageManager.java b/test-mock/src/android/test/mock/MockPackageManager.java index 13e3693cada0..41cde175759d 100644 --- a/test-mock/src/android/test/mock/MockPackageManager.java +++ b/test-mock/src/android/test/mock/MockPackageManager.java @@ -108,6 +108,12 @@ public class MockPackageManager extends PackageManager { throw new UnsupportedOperationException(); } + /** @hide */ + @Override + public Intent getCarLaunchIntentForPackage(String packageName) { + throw new UnsupportedOperationException(); + } + @Override public int[] getPackageGids(String packageName) throws NameNotFoundException { throw new UnsupportedOperationException(); diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java index d9d4eeba900f..1618e07a79c0 100644 --- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java +++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java @@ -268,6 +268,31 @@ public class IpSecServiceParameterizedTest { anyInt()); } + public void testCreateTwoTransformsWithSameSpis() throws Exception { + IpSecConfig ipSecConfig = new IpSecConfig(); + addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); + addAuthAndCryptToIpSecConfig(ipSecConfig); + + IpSecTransformResponse createTransformResp = + mIpSecService.createTransform(ipSecConfig, new Binder()); + assertEquals(IpSecManager.Status.OK, createTransformResp.status); + + // Attempting to create transform a second time with the same SPIs should throw an error... + try { + mIpSecService.createTransform(ipSecConfig, new Binder()); + fail("IpSecService should have thrown an error for reuse of SPI"); + } catch (IllegalStateException expected) { + } + + // ... even if the transform is deleted + mIpSecService.deleteTransform(createTransformResp.resourceId); + try { + mIpSecService.createTransform(ipSecConfig, new Binder()); + fail("IpSecService should have thrown an error for reuse of SPI"); + } catch (IllegalStateException expected) { + } + } + @Test public void testDeleteTransform() throws Exception { IpSecConfig ipSecConfig = new IpSecConfig(); |